설명 블로그

modelformset changing query set 

modelformset은 기본으로 이미 입력된 모든 데이터를 보여준다. 이를 바꿀때 사용

https://docs.djangoproject.com/en/3.0/topics/forms/modelforms/#changing-the-queryset

formset

https://docs.djangoproject.com/en/3.0/topics/forms/formsets/

basemodelformset

https://docs.djangoproject.com/en/3.0/topics/forms/modelforms/#django.forms.models.BaseModelFormSet

django에 mysql을 사용하려고 했으나 연결이 어려웠다. 아래 방법들을 다 시도해보고 결국 export PATH=$PATH:/usr/local/mysql/bin/ 를 통해 mysql config위치를 다시 정해 주고 pymysql을 설치하고 django downgrade로 문제 해결 했다.

pymysql 설치 https://stackoverflow.com/a/56312295

django downgrade https://stackoverflow.com/a/58448370

최종적으로 사용된 modules

image
image

.

.

.

image

.

.

.

image

.

.

.

image

위와 같은 error 발생

.

.

ModuleNotFoundError: No module named ‘MySQLdb’

https://stackoverflow.com/questions/53024891/modulenotfounderror-no-module-named-mysqldb

unable to install mysqlclient in python 3.7.3
https://stackoverflow.com/questions/57808191/unable-to-install-mysqlclient-in-python-3-7-3

What’s the difference between MySQLdb, mysqlclient and MySQL connector/Python?

https://stackoverflow.com/questions/43102442/whats-the-difference-between-mysqldb-mysqlclient-and-mysql-connector-python/46396881#46396881

pip install mysql-python fails with EnvironmentError: mysql_config not found
https://stackoverflow.com/questions/5178292/pip-install-mysql-python-fails-with-environmenterror-mysql-config-not-found

Import error :No module named MYSQLdb

https://askubuntu.com/questions/583415/import-error-no-module-named-mysqldb/1048285#1048285

Django – installing mysqlclient error: mysqlclient 1.3.13 or newer is required; you have 0.9.3

https://stackoverflow.com/questions/55657752/django-installing-mysqlclient-error-mysqlclient-1-3-13-or-newer-is-required

original source : https://www.micahcarrick.com/django-email-authentication.html

아래 예제 코드에 오류가 있어서 2군데 수정하고 기본적으로 intent 의 수정이 필요하다.

django는 username과 password를 이용해 authentication 작업을 하는데 이를 email 과 password로 바꾸는 작업을 설명하고 있다.

Django Authentication using an Email Address

The Django authentication system provided in django.contrib.auth requires the end user to authenticate themselves using a username and password. However, it is often desireable to allow users to log in using an email address rather than a username. There are a few different ways to accomplish this and a lot of discussion on the topic.

In this approach, I use a custom authentication backend to authenticate a user based on his or her email address, I hide the username from the end user, I generate a random username for the user when creating an account, and I manually add a unique index to the email column in the database (this is a bit of a “hack”).

Why email authentication?

The web has evolved and these days many of us have dozens (hundreds?) of accounts around the web. Remembering all those usernames and passwords can be a real chore. That “forgot password” feature suddenly becomes a standard step in the log in process for many users. When ease-of-use is paramount in your authentication system, such as customer accounts on e-commerce websites, you want to require as little effort from the end user as possible. Most people already remember their email address. One less piece of information to remember.

Why not email authentication?

Yes, this post is about using email authentication, but it has it’s down side as well. We know users forget their passwords quite often. Users can also lose their email address when they change jobs, schools, or their domain name expires. If a user has lost access to the email they used in your system and they do not remember their password then there is nothing they can do short of starting a new account on your site (unless you implement something to specifically address this scenario). For some applications this is an acceptable trade-off for the usability gained by using email authentication.

Problems Presented with Email Authentication in Django

The email address is not unique.

The Django authentication system uses the a username to uniquely identify a user. While this is often used as a “display name” as well, it’s primary function is as a unique identifier for a user. In theory, Django’s auth system could allow two users to share the same email address and thus, the email address does not uniquely identify a user.

There is no database index on the email address.

If the authentication system is going to be querying users on their email address, the database column storing that email address would need to have an index. The datatbase table created by the Django authentication, auth_user, does not have any index on the email address, let alone a unique index.

The username is limited to 30 characters.

Some people implement email authentication in Django by putting the email address into the username field. The problem with this is that the username field is limited to 30 characters and many (about 15% on one of my websites) are longer than 30 characters.

Other code relies on django.contrib.auth.

There are a lot of other Django apps, both built-in and 3rd party, that make use of Django’s authentication system. Thus, it is ideal to work with Django’s authentication system opposed to “rolling your own” system.

A Custom Backend Solution for Email Authentication in Django

The approach I have opted for begins with a custom authentication backend. The code below defines the backend that django.contrib.auth will use instead of the default backend. The username passed to the authenticate() method is assumed to be an email address and the user is queried based on the email instead of the username.

(아래 코드에서 from django.contrib.auth.models import User, check_password 이렇게 원래는 되어있었으나 check_password를 삭제했다.)

backends.py

from django.contrib.auth.models import User
class EmailAuthBackend(object):
	"""
	Email Authentication Backend

	Allows a user to sign in using an email/password pair rather than
	a username/password pair.
	"""
 
	def authenticate(self, username=None, password=None):
		""" Authenticate a user based on email address as the user name. """
		try:
			user = User.objects.get(email=username)
			if user.check_password(password):
				return user
			except User.DoesNotExist:
				return None
 
	def get_user(self, user_id):
		""" Get a User object from the user_id. """
		try:
			return User.objects.get(pk=user_id)
	except User.DoesNotExist:
		return None

You can then use the AUTHENTICATION_BACKENDS setting in your settings.py file to tell the django authentication system to use your custom backend.

settings.py

AUTHENTICATION_BACKENDS = ('backends.EmailAuthBackend',)

Renaming the “Username” Field to “Email address”

Since the custom authorization backend assumes the username passed to it is an email address, the standard authentication form works just fine. The user just enters an email address instead of a username. However, the form still has the username field and that field is still labeled “Username”.

Since I prefer more granular control over the layout of the forms in the authentication process, I opted to let the login form template handle changing the label of the authentication form. An alternative approach would have been to subclass django.contrib.auth.forms.AuthenticationForm and rename the field’s label there.

templates/login_form.html (example snippet)

<form action="." method="post">
	{% csrf_token %}
	<input type="hidden" name="next" value="{{ next }}" />
	{{ form.non_field_errors }}
	{% for field in form %}
 <div class="field-wrapper">
	<div class="label-wrapper">
		{% if field.name == "username" %}
			Email address
		{% else %}
			{{ field.label_tag }}
		{% endif %}
		{% if field.field.required %}<span class="required">*</span>{% endif %}
	</div>
	<div class="value-wrapper">
		{{ field }}
		{{ field.errors }}
	</div>
 </div>
 {% endfor %}
 <div class="submit-wrapper">
 <input type="submit" value="Sign In" />
 </div>
</form>

A Custom Sign Up Form (User Creation Form)

Since an email address is now required to authenticate a user, it needs to be a required field on the user creation form as well. This can be done by subclassing the UserCreationForm.

(아래코드에서 except 구문아래 pass가 없었는데 내가 넣었다.)

forms.py

from django.contrib.auth.forms import UserCreationForm
from django.contrib.auth.models import User
from django import forms

class SignUpForm(UserCreationForm):
	""" Require email address when a user signs up """
	email = forms.EmailField(label='Email address', max_length=75)
 
	class Meta:
		model = User
		fields = ('username', 'email',)
	def clean_email(self):
		email = self.cleaned_data["email"]
	try:
		user = User.objects.get(email=email)
		raise forms.ValidationError("This email address already exists. Did you forget your password?")
	except User.DoesNotExist:
                pass
		return email
	def save(self, commit=True):
		user = super(UserCreationForm, self).save(commit=False)
		user.set_password(self.cleaned_data["password1"])
		user.email = self.cleaned_data["email"]
		user.is_active = True # change to false if using email activation
		if commit:
			user.save()
		return user

Now the email address is added to the form, however, the username is still a required field as well. That may suit your needs, however, my goal is to keep the process as simple as possible for the end user. I do not want to remove the username, I just want to hide it from the end user. So I simply hide the username field in the template for the form and then auto-generate a random username in the view.

templates/sign_up.html (example snippet)

<form action="." method="post">
	{% csrf_token %}
	{{ form.non_field_errors }}
	{% for field in form %}
		{% if field.name != "username" %}
			<div class="field-wrapper">
				<div class="label-wrapper">
					{{ field.label_tag }}
					{% if field.field.required %}<span class="required">*</span>{% endif %}
				</div>
				<div class="value-wrapper">
					{{ field }}
					{{ field.errors }}
				</div>
			</div>
		{% endif %}
	{% endfor %}
	<div class="submit-wrapper">
		<input type="submit" value="Sign Up"/>
	</div>
</form>

Generating a Random Username in the View

Since the username field was omitted from the sign up form template, the view that processes the form needs to create one. The example view below generates a random 30-character username.

from django.template import RequestContext
from django.shortcuts import render_to_response
from django.http import HttpResponseRedirect
from forms import SignUpForm
from random import choice
from string import letters

def sign_up(request):
	""" User sign up form """
	if request.method == 'POST':
		data = request.POST.copy() # so we can manipulate data
	
	# random username
	data['username'] = ''.join([choice(letters) for i in xrange(30)])
	form = SignUpForm(data)
	
	if form.is_valid():
		user = form.save()
		return HttpResponseRedirect('/sign_up_success.html')
	else:
		form = SignUpForm()

	return render_to_response('sign_up.html', {'form':form}, context_instance=RequestContext(request))

Adding a Unique Index to the Email Column

The only part of this email authentication solution that I really do not like is that I have am manually adding a unique index to the email address column in the database (I use MySQL). Please post a comment with your suggesions for a better solution.

I know of some people who use the email address in a custom profile, however I don’t like the redundancy nor having the primary unique identifier for a user in a separate table. The ideal solution for me would be to have some code that can unobtrusively add a unique index to the auth_user table through Django’s database abstraction.

SQL

ALTER TABLE auth_user ADD UNIQUE INDEX (email);

required form field를 위한 model field 설정

https://docs.djangoproject.com/en/3.0/topics/forms/modelforms/#field-types

https://stackoverflow.com/a/27036431

p103 Model EmailField()

p104 null=True , blank=True

p105 model verbose_name option

p106-7 admin.py admin.ModelAdmin을 통해 admin 에서 볼수 있는 model들의 설정을 바꿀수 있다.

p107 admin.py admin.ModelAdmin 를 통해서 admin 화면 customizing이 가능하다.

p120 HttpRequest.META 안에 각종 header정보가 있다.

p124- 126 basic form GET 사용법

p133 basic form POST 작동원리 and 에러 

forms.ModelForm customizing하기

p136 forms.Form의 다른 widget으로 바꾸기

p138 forms.Form의 기본 validation 규칙 , 기본값 설정하기 

p139 custom validation 설정하기, label바꾸기

p140 field별로 html tag , message 출력하기

p147 공통된 url prefix를 설정하기

p162 wrapper를 이용해 여러 view들에 사전 작업을 처리할수 있다. (ex login wrapper) decorator와 같은 원리 이다.

p163 urls include

p174 template autoescape off 하는 방법

p176 {{data | default:”3 &lt; 2”}} template에서 기본값설정하는데 special character escaped

p256 cookies에 접근하는 법

p258 session 이용

p261 session check

p264 request.user

p265 request.user.is_authenticated()

p277 auth.authenticate() 와 auth.login()와 auth.logout()

p269 login_required decorator

p270 permission_required decorator

user_passes_test()

p271 creating user, set password , check password

  • User.objects.create_user(), User.set_password(), User.check_password()

p273 template에서 authentication data 사용하기

django docs Form 기본

django docs ModelForm

Using the Django authentication system

https://docs.djangoproject.com/en/3.0/topics/auth/default/#module-django.contrib.auth.forms

creating form from model

https://docs.djangoproject.com/en/3.0/topics/forms/modelforms/#django.forms.ModelForm

working with form

https://docs.djangoproject.com/en/3.0/topics/forms/

modelform customizing

https://colinkingswood.github.io/Model-Form-Customisation/

customizing UserCreationForm

https://stackoverflow.com/a/5745488

adjusting height with bootstrap

https://www.w3schools.com/bootstrap4/bootstrap_utilities.asp

https://getbootstrap.com/docs/4.0/utilities/sizing/

(input 의 높이를 지정하는 방법으로 percentage사용불가)

PasswordInput() 사용예시

https://www.programcreek.com/python/example/107521/django.forms.PasswordInput

message framework (ontime message to next view)

https://docs.djangoproject.com/en/2.0/ref/contrib/messages/

using authentication system in django

https://docs.djangoproject.com/en/3.0/topics/auth/default/

AuthenticationForm 수정 custom customizing하기

https://stackoverflow.com/a/12333660

AuthenticationForm수정 custom customizing하기

https://stackoverflow.com/a/12333660

original source : https://docs.djangoproject.com/en/3.0/topics/signals/

Signals

Django includes a “signal dispatcher” which helps allow decoupled applications get notified when actions occur elsewhere in the framework. In a nutshell, signals allow certain senders to notify a set of receivers that some action has taken place. They’re especially useful when many pieces of code may be interested in the same events.

Django provides a set of built-in signals that let user code get notified by Django itself of certain actions. These include some useful notifications:

Sent before or after a model’s save() method is called.

Sent before or after a model’s delete() method or queryset’s delete() method is called.

Sent when a ManyToManyField on a model is changed.

Sent when Django starts or finishes an HTTP request.

See the built-in signal documentation for a complete list, and a complete explanation of each signal.

You can also define and send your own custom signals; see below.

Listening to signals

To receive a signal, register a receiver function using the Signal.connect() method. The receiver function is called when the signal is sent. All of the signal’s receiver functions are called one at a time, in the order they were registered.

(Signal에 특정 sender에만 반응하는 receiver를 연결, dispatch_uid를 이용 중복을 막는다.)

Signal.connect(receiver, sender=None, weak=True, dispatch_uid=None)

[source]

Parameters:

  • receiver – The callback function which will be connected to this signal. See Receiver functions for more information.
  • sender – Specifies a particular sender to receive signals from. See Connecting to signals sent by specific senders for more information.
  • weak – Django stores signal handlers as weak references by default. Thus, if your receiver is a local function, it may be garbage collected. To prevent this, pass weak=False when you call the signal’s connect() method.
  • dispatch_uid – A unique identifier for a signal receiver in cases where duplicate signals may be sent. See Preventing duplicate signals for more information.

Let’s see how this works by registering a signal that gets called after each HTTP request is finished. We’ll be connecting to the request_finished signal.

Receiver functions

First, we need to define a receiver function. A receiver can be any Python function or method:

def my_callback(sender, **kwargs):
    print("Request finished!")

Notice that the function takes a sender argument, along with wildcard keyword arguments (**kwargs); all signal handlers must take these arguments.

We’ll look at senders a bit later, but right now look at the **kwargs argument. All signals send keyword arguments, and may change those keyword arguments at any time. In the case of request_finished, it’s documented as sending no arguments, which means we might be tempted to write our signal handling as my_callback(sender).

This would be wrong – in fact, Django will throw an error if you do so. That’s because at any point arguments could get added to the signal and your receiver must be able to handle those new arguments.

Connecting receiver functions

두가지 방법이 있으며 하나는 Signal.connect()를 이용하는 것과 decorator를 이용하는 것이다.

There are two ways you can connect a receiver to a signal. You can take the manual connect route:

from django.core.signals import request_finished

request_finished.connect(my_callback)

Alternatively, you can use a receiver() decorator:

receiver(signal)

[source]

Parameters:signal – A signal or a list of signals to connect a function to.

Here’s how you connect with the decorator:

from django.core.signals import request_finished
from django.dispatch import receiver

@receiver(request_finished)
def my_callback(sender, **kwargs):
    print("Request finished!")

Now, our my_callback function will be called each time a request finishes.

Where should this code live?

Strictly speaking, signal handling and registration code can live anywhere you like, although it’s recommended to avoid the application’s root module and its models module to minimize side-effects of importing code.

(receiver는 보통 signals이라는 module에 넣어 보관한다.)

In practice, signal handlers are usually defined in a signals submodule of the application they relate to. Signal receivers are connected in the ready() method of your application configuration class. If you’re using the receiver() decorator, import the signals submodule inside ready().

https://youtu.be/Kc1Q_ayAeQk?t=632

Note

The ready() method may be executed more than once during testing, so you may want to guard your signals from duplication, especially if you’re planning to send them within tests.

Connecting to signals sent by specific senders

(sender를 지정해서 특정 작업에만 반응하게 한다.)

Some signals get sent many times, but you’ll only be interested in receiving a certain subset of those signals. For example, consider the django.db.models.signals.pre_save signal sent before a model gets saved. Most of the time, you don’t need to know when any model gets saved – just when one specific model is saved.

In these cases, you can register to receive signals sent only by particular senders. In the case of django.db.models.signals.pre_save, the sender will be the model class being saved, so you can indicate that you only want signals sent by some model:

from django.db.models.signals import pre_save
from django.dispatch import receiver
from myapp.models import MyModel


@receiver(pre_save, sender=MyModel)
def my_handler(sender, **kwargs):
    ...

The my_handler function will only be called when an instance of MyModel is saved.

Different signals use different objects as their senders; you’ll need to consult the built-in signal documentation for details of each particular signal.

Preventing duplicate signals

In some circumstances, the code connecting receivers to signals may run multiple times. This can cause your receiver function to be registered more than once, and thus called multiple times for a single signal event.

If this behavior is problematic (such as when using signals to send an email whenever a model is saved), pass a unique identifier as the dispatch_uid argument to identify your receiver function. This identifier will usually be a string, although any hashable object will suffice. The end result is that your receiver function will only be bound to the signal once for each unique dispatch_uid value:

from django.core.signals import request_finished

request_finished.connect(my_callback, dispatch_uid="my_unique_identifier")

Defining and sending signals

(커스텀 Signal 이용하기)

Your applications can take advantage of the signal infrastructure and provide its own signals.

When to use custom signals

Signals are implicit function calls which make debugging harder. If the sender and receiver of your custom signal are both within your project, you’re better off using an explicit function call.

Defining signals

class Signal(providing_args=list)

[source]

All signals are django.dispatch.Signal instances. The providing_args is a list of the names of arguments the signal will provide to listeners. This is purely documentational, however, as there is nothing that checks that the signal actually provides these arguments to its listeners.

For example:

import django.dispatch

pizza_done = django.dispatch.Signal(providing_args=["toppings", "size"])

This declares a pizza_done signal that will provide receivers with toppings and size arguments.

Remember that you’re allowed to change this list of arguments at any time, so getting the API right on the first try isn’t necessary.

Sending signals

There are two ways to send signals in Django.

Signal.send(sender, **kwargs)

[source]

Signal.send_robust(sender, **kwargs)

[source]

To send a signal, call either Signal.send() (all built-in signals use this) or Signal.send_robust(). You must provide the sender argument (which is a class most of the time) and may provide as many other keyword arguments as you like.

For example, here’s how sending our pizza_done signal might look:

class PizzaStore:
    ...

    def send_pizza(self, toppings, size):
        pizza_done.send(sender=self.__class__, toppings=toppings, size=size)
        ...

Both send() and send_robust() return a list of tuple pairs [(receiver, response), ... ], representing the list of called receiver functions and their response values.

send() differs from send_robust() in how exceptions raised by receiver functions are handled. send() does not catch any exceptions raised by receivers; it simply allows errors to propagate. Thus not all receivers may be notified of a signal in the face of an error.

send_robust() catches all errors derived from Python’s Exception class, and ensures all receivers are notified of the signal. If an error occurs, the error instance is returned in the tuple pair for the receiver that raised the error.

The tracebacks are present on the __traceback__ attribute of the errors returned when calling send_robust().

Disconnecting signals

Signal.disconnect(receiver=None, sender=None, dispatch_uid=None)

[source]

To disconnect a receiver from a signal, call Signal.disconnect(). The arguments are as described in Signal.connect(). The method returns True if a receiver was disconnected and False if not.

The receiver argument indicates the registered receiver to disconnect. It may be None if dispatch_uid is used to identify the receiver.