This article is the last day of Django Advent Calendar 2019.
Nice to meet you. Thank you.
I usually use Djnago to develop web applications.
I enjoyed watching this year's Django Advent Calendar 2019 every day. All the articles were interesting and educational. So, in this article, the last day of this calendar, I'd like to organize some basic and personal tips for Django. I hope this article has contributed to the further spread of Django.
-[Form Validation](#Form Validation) -[Send Http404](Send # http404) -[Execute instance acquisition and send Http404 if the object does not exist](# Perform instance acquisition and send -http404- if the object does not exist) -[Perform time-consuming processing in advance using Pickle](# Perform time-consuming processing in advance using pickle) -[Perform time-consuming processing in advance using Model](# Perform time-consuming processing in advance using model) -[Use login authentication function](#Use login authentication function) -[Get the data stored in Model for each logged-in user](Get the data stored in #model for each logged-in user) -[Extract object by OR condition](Extract object by #or condition) -[Get loop counter with Template](Get loop counter with #template) -[Specify list array number with Template](Specify list array number with #template) -[(Extra edition) Use Cloudinary as image storage](# Extra edition Use cloudinary as image storage)
When you receive a value from the input screen of the Web and set it in Model, you can verify whether there is an invalid value. By using the Djnago standard is_valid function, for example, if an item other than a numerical value is entered in the IntegerField item, or if the required item is blank, an Error can be sent.
if form.is_valid(): #Form validation
#processing
# ...
If you want to branch the process by receiving an argument for each URL to access, it is better to set raise Http404
in else.
You can avoid Server Error (500)
when an argument is passed in an unexpected URL in this function by doing the following.
views.py
from django.http import Http404
def sample(request, mode):
if mode == 'hoge':
#Process 1
elif mode == 'fuga':
#Process 2
else:
raise Http404("No User matches the given query.")
You may want to use get_object_or_404
when issuing a query to get an instance from Model.
In the example below, we are getting an object with a primary key of 1 from MyModel
, but if that object does not exist, we will send an Http404.
This should avoid inadvertently causing a Server Error (500)
.
views.py
from django.shortcuts import get_object_or_404
def my_view(request):
my_object = get_object_or_404(MyModel, pk=1)
When you do a lot of processing in View, it may take a long time and increase the response time.
In such cases, you may want to use pickle.dump
and pickle.load
.
As a pre-process, process halfway, make the resulting Python object pickle, and load it for use in this process.
Doing so will greatly improve response time.
python
#Pyhton object through such a function->Pickle
def pickle_dump(obj, path):
with open(path, mode='wb') as f:
pickle.dump(obj,f)
#When using from this process, pickle->Return to python object
def pickle_load(path):
with open(path, mode='rb') as f:
data = pickle.load(f)
return data
After that, it is a good idea to call the preprocessing regularly with the job scheduler and automate it.
If you're using Heroku to put your Djnago Project into production, trying the above methods may not work. It's due to the specification (https://devcenter.heroku.com/articles/active-storage-on-heroku) that Heroku's filesystem is temporary. Even if you pickle.dump the result of the process, the pickle will not be saved on your Djnago Project.
In such a case, you may want to store the Python object in Model.
To store a Python object in Model as it is, you need to prepare Custom Model Fields. However, if it is a list type Python object, you can use Django standard CharField by converting it to json format.
models.py
class Pickle(models.Model):
sample = models.CharField(max_length=255, null=True)
def set_sample(self, x):
self.sample = json.dumps(x)
def get_sample(self):
return json.loads(self.sample)
Prepare the Model class method as described above and operate the Model through the setter or getter. You should be able to handle many cases by using json and CharField well like this. For example, pandas.DataFrame can also be stored in Model by type conversion with pandas.DataFrame-> numpy.ndarray-> list-> json.
You will often use the login authentication function when creating a web application.
Django provides login authentication as a standard feature. By using these, you can quickly implement login authentication. It is also explained in the Official Documents.
Implementing the authentication function is a three-step process.
$ django-admin startapp accounts
INSTALLED_APPS = [
...
'accounts.apps.AccountsConfig', #add to
]
#Redirect to top page after login
LOGIN_REDIRECT_URL = '/hoge/'
This completes the implementation of the login authentication function.
Then, by adding @ login_required
to the View function, access can be restricted by login authentication.
@login_required
def sample(request):
pass
By the way, the user registration function is not provided as a standard function of Djnago, but you can create it yourself. You can also customize the login screen and log-out screen.
For reference, the code for implementing the user registration function is shown below.
accounts/urls.py
urlpatterns = [
path('signup/', views.SignUpView.as_view(), name='signup'),
]
accounts/views.py
from django.contrib.auth.forms import UserCreationForm
from django.urls import reverse_lazy
from django.views import generic
class SignUpView(generic.CreateView):
form_class = UserCreationForm
success_url = reverse_lazy('login')
template_name = 'accounts/signup.html'
If you implement login authentication, you will surely have a requirement to extract objects for each logged-in user from all the objects stored in Model. In such a case, you can extract only the logged-in user's object by setting the following conditions with the filter function.
views.py
from models import Content
@login_required
def sample(repuests):
contents = Content.objects.all().filter(user_id=request.user.id)
When extracting an object from a Model with Django, the AND condition should be overlaid with the filter function, but the OR condition should use the Q
library.
For example, you can extract only objects with dates 2019-12-24
, 2019-12-25
, or 2019-12-26
by writing:
views.py
from django.db.models import Q
from models import Content
def sample(request):
contents = Content.objects.filter(
Q(date='2019-12-24') | Q(date='2019-12-25') | Q(date='2019-12-26')
)
When turning the list passed from View with for in Template, You can get the loop counter in the for by implementing as follows.
{% for list in lists %}
{{ forloop.counter }}
{% endfor %}
Furthermore, you can get various loop counters by replacing the counter
part with counter0
(in order from 0) or revcounter
(in reverse order).
For the list passed from View even in Template You can retrieve the element by specifying the array number as in Python.
{{ objects.0 }}
This isn't a tip, but I usually use Cloudinary as my image storage.
As mentioned in [Pre-do time-consuming processing using Model](# Pre-do time-consuming processing using model), you can't save files to Django Project running on Heroku. So if you want to upload images or manage the uploaded images with the Django application on Heroku, you need to have image storage.
You can use Cloudinary to work with image data in your Django application.
Cloudinary Official Documentation
There are three things you need to do to use Cloudinary:
--Model definition --settings.py settings --Adding Heroku Add-ons
models.py
from cloudinary.models import CloudinaryField
class Image(models.Model):
picture = CloudinaryField('picture')
settings.py
# Add
CLOUDINARY_STORAGE = {
'CLOUD_NAME': '*****',
'API_KEY': '*****',
'API_SECRET': '*****'
}
# ...
# Add
DEFAULT_FILE_STORAGE = 'cloudinary_storage.storage.MediaCloudinaryStorage'
If you set it as above, you can use it in the same way as ʻImageField`.
Thank you for reading to the end. How was that. If there are other ways like this, I would appreciate it if you could comment.
Have a good Django life!
Recommended Posts