I am new to creating models in Django and I want to make a model, which allows you to fill in the title, some texts for on the template and the path to this template. I am trying to get the answer off of the Django Example Project, but I just don't understand the models, is there anybody who can help me on how to write such a model?
My code in the models.py
class Project(models.Model):
project_name = models.Charfield(max_length=20)
project_title = models.Charfield(max_length=100)
project_information = models.Charfield(max_length=400)
where project_name is the link to the template
I don't know if this is a correct begin or that it should be something completely different.
I'm assuming that you're asking ways to use the information in a model (object data) in a template.
If so, template isn't created in a model, you can send your object(s) to a template by rendering a template in the corresponding view of the model. You'll append the necessary information (queryset and other optional dict elements) in the view and send it to the template.
How you can use the information in the template depends on your view method. For function based views like this:
def home_view(request):
contests = Contests.objects.filter(id<5)
context={'contests':contests}
return render(request, 'home/home.html', context)
You can access the data in a queryset in the template, like this:
{% for contest in contests %}
//do something with the single contest data
{% endfor %}
You can directly access the non-plural values like this:
{% if not random_contest == None %}
//do something with the random contest data
{% endif %}
Additionally, there are class based views but it looks like you are at a very early stage of learning Django, so you won't need it for now.
See the docs about views.
See the docs about shortcut functions.
Related
I may get blowback from asking this question but it's something I've wondered about for a while so here goes.
In a Django template, you can use .all to get the queryset of things, like so:
{% for prerequisite in object.prerequisites.all %}
<li class="list-group-item">{{ prerequisite.text }}</li>
{% endfor %}
The model in this case looks like this, but the only relevant piece of information is that object above has a relation to the Prerequisite model through the ForeignKey.
class Prerequisite(models.Model):
content = models.ForeignKey(Content, on_delete=models.CASCADE,
related_name='prerequisites')
text = models.CharField(max_length=100)
def __str__(self):
return str(self.text)
My question is
Is it best-practice to call Django querysets in the template, (ie: object.prerequisites.all) or should one pass it in the view through the context?
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['prerequisites'] = self.object.prerequisites.all()
return context
It's really convenient to do querysets in the template, but it seems like it should be business logic located in the view. Does Django have a specific stance on this?
according to django documentation:
https://docs.djangoproject.com/en/4.1/#the-view-layer
The view layer -
Django has the concept of “views” to encapsulate the logic responsible for processing a user’s request and for returning the response.
https://docs.djangoproject.com/en/4.1/#the-template-layer
The template layer -
The template layer provides a designer-friendly syntax for rendering the information to be presented to the user.
i have different example, i know a lot of programmers loves to move buisness logic from views.py to serializer.py, even if original purpose of serialezers life is - to serialize
i believe the most appropriate way is to pass your data through context in the views.
Views originally is all your buisness logic, serializer suppose only serialization, and templates purpose is to show html page, python wasn't originaly desined to manipulate html page
I have a model for a company.
Then I have a base model for company posts. It contains common posts attributes. An attribute is the company that publishes the posts. It refers to the Company model with a ForeignKey.
Finally I have a child model (based on the CompanyPost base model) for posts of type A:
class Company(models.Model):
name = models.CharField(...)
...
class CompanyPost(models.Model):
company = models.ForeignKey(Company,...)
...
class PostA(CompanyPost):
name = ...
In a template I want to loop over posts of type A published by a specific company.
I tried these variants:
1)
{% for postA in company.companyposts_set.all.postA_set.all %}
...
2)
{% for companyposts in company.companypost_set.all %}
{% for postA in companyposts.postA_set.all %}
...
{% endfor %}{% endfor %}
I tried other sub-variants of the above. None seems to work.
I know that I can easily prepare the set in the view, like:
postsA = PostA.objects.filter(company__pk=pk)
And pass postsA to the template context, but I'm wondering whether there is a way to loop over related models' children in the template.
(note: looping over companyposts works. But I get of course all types of posts, like postB etc.:
{% for post in company.companypost_set.all %}
That is why I tried variant 2) above to loop again over the results.)
Thank you in advance.
UPDATE:
Thank you all for your answers.
I understand that, by choosing model inheritance, I chose a convoluted solution.
In the present post I'm asking whether displaying related model's children in a template is possible. In order not to confuse questions, in this question I explain why I used concrete model inheritance and ask what would be a better solution.
If you don't want to define it in the views, you could define it as a property of Company objects.
#property
def post_a_set(self):
return PostA.objects.filter(company__pk=self.pk)
I'm pretty sure it's the model inheritance that is causing the problems, and dimly remember seeing something like his documented. I'd echo, do you really need concrete model inheritance here? Other approaches are wider CompanyPost objects with a post_type choices field and other fields null or blank if inappropriate; or a post_type field and the data that applies only to that type stored as a JSON string or (if you are using Postgresql) a JSONField.
I have a foreign key and I'm using the related_name field like so:
class Pizza(models.Model):
...
restaurant = models.ForeignKey('Restaurant', related_name='pizzas_offered')
active = models.BooleanField(...)
...
Example from the view:
my_restaurant = get_object_or_404(Restaurant, pk=id)
In any template I can run something like my_restaurant.pizzas_offered.all to get all the pizzas belonging to a particular restaurant. However, I only want the pizzas that are active (active=True). Is there a way to retrieve this subset in the template, without having to pass a separate variable in the view? Please note that I always want to only show the active pizzas only so if I have to make a change in the model to make this happen, that is fine too.
NOTE: in the view I can simply pass my_restaurant.pizzas_offered.filter(active=True) but it returns an error when I use it in the template:
{% for details in my_restaurant.pizzas_offered.filter(active=True) %}
{{ details.name }}
{% endfor %}
It returns this error:
Could not parse the remainder: '(active=True)'
There are some reasons why I want to do this on template level and not in the view (main reason: I often loop through all the records in the database and not just one restaurant, so I can't just query for the one record). So my question is how to do this on template-level.
You need to create a Manager for your Pizza model and set the Meta.base_manager_name:
class PizzaManager(models.Manager):
def active(self):
return self.filter(status=True)
class Pizza(models.Model):
...
objects = PizzaManager()
class meta:
base_manager_name = 'objects'
Now you can use the method active in your template:
{% for details in my_restaurant.pizzas_offered.active %}
...
{% endfor %}
For more information you can read the documentation about Default and Base managers.
I have a model with various different field types that I want the Algolia search engine to index correctly. So far I have been able to handle models.char_fields pretty straightforwardly - I'm now thinking, what's the best way to index various other field types (e.g., ForeignKey "objects", ImageFields, DateTime fields etc etc).
One thing I have noticed is that Algolia will fetch and store a DateTimeField as Unix standard time...so, originally I thought I could render something human readable on the template using {% humanize %}, but to no luck.
I was wondering if anyone knew of ways of dragging out useful information from the model - one idea I have had is to grab the object within the view and then bring out a unique identify for each returned object, then work some conditional flow to marry up that unique ident to the model, then I can work with that model as normal...? Such as:
def instant_search(request):
posts = Post.published.all()
context = {
'appID': settings.ALGOLIA['APPLICATION_ID'],
'searchKey': settings.ALGOLIA['SEARCH_API_KEY'],
'indexName': get_adapter(Post).index_name,
'posts': posts,
}
return render(request, 'blog/frame/instant_search.html', context)
The within the template I can use {% for posts in post %} {% if post.id = _highlightResult.id.value %} ...do some stuff {% endif %} {% endfor %}
If this isn't quite fast enough (and I'm pretty much guaranteeing it won't) I was wondering if Algolia can handle key information, such as dragging out the url for an image which is defined in the model as an ImageField e.g., much like I would with e.g., post.image.url in the template or a human readable value taken from a DateTime field models.DateTimeField(default=timezone.now) in the model. It would be really nice to do this as Algolia indexes the defined model fields...
Just figured this one out:
In models.py I had to define attribute methods to obtain a manipulated bespoke value for Algolia to understand:
e.g., I have defined the following in the class for the model I wish to index:
def image_url(self):
"""Get upload_to path specific to this photo: Algolia recognizable format."""
return self.image_scroll_1.url
def published_date(self):
"""Returns a humanized date format for Algolia indexing."""
humanized_published_date = str(self.publish.strftime("%A, %d, %B %Y %I:%M%p"))
return humanized_published_date
Hopefully this will help anyone else who is working with Algolia and working off various tutorials (I'm using Django by Example).
These can then be referenced in index.py as follows:
from algoliasearch_django import AlgoliaIndex
class PostIndex(AlgoliaIndex):
fields = ('title', 'post_author', 'lead_in', 'published_date', 'keyword_tags', 'image_url', 'get_absolute_url')
Along with any other optional parameters you may like.
I have this model Note:
class Note(models.Model):
category = models.ForeignKey(Category)
author = models.ForeignKey('auth.User')
title = models.CharField(max_length=40)
text = models.TextField()
created = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
And I want to display this form:
class NoteEditForm(forms.ModelForm):
class Meta:
model = Note
fields = ('title', 'text')
in a template, but I want it to appear for each existing Note object in the database (it has to be that way). I've done something like that but then I hardcoded the form, pointing to the edit view URL with each object pk as a parameter; but I'm sure it has to be a clearer way, just I haven't found it. Could you guys help me with that? Thanks!
The easiest way to do this is to use a formset (also see model formsets).
For your Note model and NoteEditForm you could do something like this. You'd usually put this wherever you've defined your NoteEditForm but it can go in another file, such as views.py.
from django.forms import modelformset_factory
NoteEditFormSet = modelformset_factory(Note, form=NoteEditForm)
Using NoteEditFormSet in a view and template is almost the same as using a regular form, but there are a few differences to be aware of if you want to do anything complicated so have a look at the docs (view and template). If that's not clear enough, add a few details of what you're trying to do in your view and template and I'll try to help.
By default the formset will use Note.objects.all() as its queryset, which is what you say you want, but you can change that (details are covered in the docs).
Update:
To save an individual Note with an AJAX request I would add a second view to handle those requests. So if your formset for all Notes is served by a view at /notes/, you could add a view to handle your AJAX request at /notes/<note_id>/ (obviously just an example, adjust to fit your URL structure).
Then your JS on the /notes/ page is responsible for serializing the data for a single note and making the request to /notes/<note_id>/ (remember the CSRF token).
The HTML inputs generated for the formset have their IDs prefixed with something like id_form-<number>- and there are hidden inputs containing Note primary keys which will let you work out which ID prefix applies to each note.
I would think about doing it like this
{% for note in Notequeryset %}
<form action={% url 'url_name_to_form' pk={{note.pk}} %}>
{{form.as_p}}
</form>
{% endfor %}
Let me know what you think