Django Loading up Class based model data on a template - django

I am new to django before this only made 1 project and that was just a follow along video so obviously the fix is probably very easy, but I am trying to make a restaurant reservation page, and later on there will be user authentication to only show the reservation that particular user made, but right now I want to display all of the reservations in my modal and trying to learn how to actually display the data.
here's the modal:
https://gyazo.com/066e3e060492990008d608a012f588f3
here's the view: https://gyazo.com/6947ed97d84b38f1e73680e28f3a0a9a
Here's the template: https://gyazo.com/966c4810b3c7f4dd8dad2e5b71c2179c
I am spent about 3 hours watching other videos on people loading there modal data in there website and when they do it I understand everything but for some reason I can't apply that to my own project, my guess is my for loop is wrong since I have a hard time with writing them and seem to always mess up, so any help so I can at least start looking in the right direction would be appreciated

When using class based views you'll have to work with django conventions. For example where you have reservations = Reservation.objects.all(), reservations is not a defined class attribute for the class based view. What you can do is rename it to queryset instead.
from django.views.generic import ListView
class ReservationList(ListView):
model = Reservation
queryset = Reservation.objects.all()
context_object_name = 'reservations' # using this attribute to alias the queryset
template_name = "make_a_reservation.html"
This way you can now use the name reservations in your template as you did with:
{% for i in reservations %}
...
{% endfor %}
That should work.

Related

Adding a new ManyToMany relationship in a form?

Django newbie here. I keep encountering the exact same design paradigm, which seems like it should be common for everyone, yet can't find out how it's supposed to be resolved.
Picture the following ManyToMany relationships:
An organization could have many members; each person could be a member of many organizations
An organization could manage many objects. An object could be in use by multiple organizations. The same applies to the relationship between people and objects.
An organization, person, or object could have multiple media elements (photos, videos, etc) of it, and a single media element could be tagged with numerous organizations, people, or objects
Nothing unusual. But how does a site user add a new person, organization, or object? It seems that if someone is filling out an "add an organization" form, in addition to choosing from existing people, objects, media, etc there should be a button for "new member", "new object", "new photo", etc, and this should take you to the forms for creating new members, objects, media, etc. And when they're done, it should go back to the previous page - whose form filled-out form entries should persist, and the newly created entry should be listed in its respective ManyToMany field.
The problem is, I don't know how to do this. I don't know how one would add a button in the middle of a form, and can't seem to find anything to clarify how to do it. I assume it would need to be a submit button, with a different name / id or some other way so that views.py can treat it differently, via flagging an "incomplete" record in the database. And the new form will need to be passed information about what page it needs to go back to when it's submitted.
Am I thinking about this correctly? If so, then I think the only knowledge I lack is how to add a second submit button in a form and how to recognize its usage in views.py.
If I'm not thinking about this correctly, however, please suggest an alternative paradigm that you think makes more sense :) This is my first Django project, so I'm learning as I do it.
ED: I'm thinking maybe instead of using {{ form.as_p }} to display it, I need to iterate over fields and use some logic to add the extra submit button in the middle as html: What's the best way to add custom HTML in the middle of a form with many fields?
Then I'll just need to figure out a way to detect which submit button was used and put some logic behind it to handle partially-submitted forms, redirecting to a form to create the relation, and then redirecting back on submit... I can probably figure this out...
The first thing I would recommend is to define your models. Lay them all out with the attributes you require. That'll be the foundation for everything else you want to accomplish. You can do everything you mentioned with Django... it's just a matter of coding it. As far as I know you would need to create each model instance separately, and then you can refer to already created instances in the create form for the Organization model for example. I would look into the docs for generic views that help you create objects easily. Then you can link to other create forms if you wish. I don't know how you can create multiple instances of different models in one form, and I don't think it would be the best way to do things even if you can. Here's an example of a model, a create form, a create view, and corresponding url:
# models.py
class Organization(models.Model):
name = models.CharField(max_length=100, null=True, blank=True)
# forms.py
class OrganizationForm(forms.ModelForm):
class Meta:
model = Organization
fields = ('name',)
def __init__(self, *args, **kwargs):
super(OrganizationForm, self).__init__(*args, **kwargs)
self.fields['name'].required = True
def clean(self):
cleaned_data = super(OrganizationForm, self).clean()
name = cleaned_data.get('name')
# views.py
class OrganizationCreateView(CreateView): # inherits from CreateView
form_class = OrganizationForm
template_name = 'create_org.html'
success_url = 'success'
def form_valid(self, form): # validate the form and save the model instance
org = form.save(commit=False)
org.save()
return redirect(reverse('redirect_url'))
# urls.py
from Project.apps.app_name import views as app_views
app_name = 'app_name'
urlpatterns = [
url(r'^create_org/$', app_views.OrganizationCreateView.as_view(), name='create_org'), # as_view() is used for class based views
# create_org.html
<form method="post">
{% crsf_token %}
{{ form.as_p }}
<a href="{% url 'app_name:create_person' %}>Create person</a> # You can link to other create views, and just style the link as a button.
<input type="submit" value="Submit">
</form>
Hope that helps.

create new parent model in CreateView in django

i am new to django and to this site, so apologies if this has been solved before but i haven't found it
So i have 2 django models
ModelA(Model):
ModelB(Model):
modelA = ForeignKey(ModelA, on_delete=models.CASCADE)
A form for the ModelB
ModelBForm(ModelForm):
class Meta:
model=ModelB
exclude=()
and a view
createModelBView(CreateView):
model = ModelB
form_class = ModelBForm
the template only does
{{form}}
When rendered, there is a dropdown list for the ModelA field so I can choose from existing instances of the ModelA, but what if a new one needs to be created? In the admin there is an option next to edit or create a new ModelA in a popup. Is there an option to do this with CreateView?
Thanks
There is no built-in functionality like that.
However you can build it easily yourself.
You will have to add a link (or a HTML form) in your template which points to the URL corresponding to the view you implemented to create the given model.
Following is a very abstract example.
In your template:
<form>
{{csrf_token}}
{{ form }}
Create model A if you want
<input type="submit" value="Submit">
<\form>
In your urls.py
url(r'^models/createA/$', views.CreateModelAView.as_view(), name="optional")
In your views.py
createModelAView(CreateView):
model = ModelA
form_class = ModelAForm
Then you'll need to create a form called ModelAForm.
On a different note, I'd suggest to start off with functional views if you're new to Django. It is more coding but you get a better feel of what's going on
In the admin there is an option next to edit or create a new ModelA in a popup. Is there an option to do this with CreateView?
No, not built in. That functionality in the admin involves a lot of front-end work involving templates and routing that would have to come from somewhere; since a Form/ModelForm instance can't assume it has access to the admin (which is a contrib module, may not be enabled, and is permission-sensitive), the infrastructure required for that can't be assumed to be available in the general case.
Keep in mind that {{ form }} doesn't even render <form> tags or any kind of submit element. It's intended to be a very, very basic way to render a very, very basic set of fields, while the admin is built specifically to be a (reasonably) powerful, flexible way to put a UI in front of your models.
You could certainly build that functionality yourself, or find a reusable app that does the same thing, but there is no facility distributed with Django to generate it automatically.

How do I get django template to recognize manytomanyfield comparison?

In my project, I am currently trying to access a manytomany field and compare it to another. I have several cases where I am doing something similar and it is working . The difference in this case is that I am trying to essentially say if one of the values in this many to many field equals a value in this other manytomanyfield, then do something....
Here is my code...
Book(models.Model):
publisher = models.ManyToManyField(Name)
Userprofile(models.Model):
publisher = models.ManyToManyField(Name)
In my Django template I am trying to do something like...
{% If user_publisher in form.initial.publisher_set.all %}
{{ publisher.name }}
{% endif %}
The example above is a simplified version of what I'm trying to do....I'm essentially trying to compare the manytomany fields and if any of the values match, perform an action. I've been at this most of today and have tried several combinations.
If I do something like
{% if user in form.initial.publisher.all %}
This works fine. I'm struggling to try and figure out how I can compare manytomanyfields. I suspect the user query works fine because it's not a manytomanyfield.
I'm thinking my format is off. I have tried to use the _set to publisher and the user publisher and when I go so far as to print the output, I am actually seeing that both the user_publisher and publisher querysets are the same. However, my django template is not showing me any results. Thanks in advance for any thoughts.
I have surfed SO all afternoon as well as Google, but can't quite figure out what I'm doing wrong.
Here is more detail to my issue. I am currently doing a CreateView whereby I am trying to get an existing record by overriding get_initial as shown below:
class BookUpdateView(CreateView):
model = Book
form_class = Book
template_name = 'Book/update_book.html'
def get_initial(self):
initial = super(BookUpdateView, self).get_initial()
book = Book.objects.get(pk=self.kwargs["pk"])
initial = book.__dict__.copy()
initial.update({
"publisher": publisher.all(),
})
return initial
Because I am copying in these records as a starting point and this is a CreateView, I don't yet have a PK or ID to query from a get_context_data perspective. Not sure how to go about getting the data that I am copying in but have not yet saved. I am actually trying to figure out if a user has the same publisher via their user profile and was able to figure out the format for get_context_data as shown below:
def get_context_data(self, **kwargs):
context = super(BookUpdateView, self).get_context_data(**kwargs)
user_publisher = self.request.user.userprofile.publisher.all()
return context
I tried to do something like....
{% if user_publisher in form.initial.publisher_set.all %}
But the template never recognizes that these two in fact do match...
When I print the variables....
They both show...
<QuerySet [<Publisher: ACME Publishing>]>
<QuerySet [<Publisher: ACME Publishing>]>
But the template does not recognize that they are the same. The screen is not rendered as I would expect when using the template language above. No errors, but end result isn't what I would expect either. Thanks in advance for any additional thoughts.
After a day or two of thinking about this, was able to figure out how to grab the PK and then use it in the context so that I could leverage the information via the context and not the form directly.
def get_context_data(self, **kwargs):
context = super(UpdateProcedureView, self).get_context_data(**kwargs)
pk=self.kwargs["pk"]
publisher = Publisher.objects.filter(pk=pk).filter(individual_access=self.request.user).count()
return context
Then in the form I can say something like if publisher > 0 then do something fancy. Thanks for the suggestions along the way to help me think this through.

Django - Checkboxes & ManytoMany relationships in TemplateView

I have a app where users can register their company and then select a number of settings from a list. Both the company and services are different models.
class Company(models.Model):
name = models.CharField(max_length=100)
(...)
class Service(models.Model):
name = models.CharField(max_length=100)
linked_companies = ManyToManyField(Company, blank=True)
What I want is to have a large list of services, with checkboxes behind their names, so the owner can quickly select the services that he wants to connect to his model. This used to be done through the admin interface, but due popular demand this feature is moved to 'the front'.
The problem is that I do not know how to fit this into the traditional (generic) view/form combinations that we' ve been using so far, since two different models are involved.
I am trying a more custom solution, but have hit a wall and I am wondering if you could help me. I have created a html page that should display both the list of services and a 'save' button.
<form action="." method="POST" class="post-form">{% csrf_token %}
<ul>
{% recursetree services %}
<li>
<label><input type="checkbox" name='service' value={{ node.pk }}><h3>{{ node.name }}</h3></label>
{% if not node.is_leaf_node %}
<ul class="children">
{{ children }}
</ul>
{% endif %}
</li>
{% endrecursetree %}
</ul>
<button type="submit" class="save btn btn-default">Add Selected
</button>
</form>
I am using the following ModelForm:
class FacetForm(forms.ModelForm):
class Meta:
model = Services
fields = ['linked_tenants', 'name']
widgets = {
'linked_tenants' : CheckboxSelectMultiple()
}
This HTML page seems to work as intended, showing a long list of services with checkboxes after their names.
However, I have trouble creating a function view. Together with a collegue the following view was created
class FacetList(TenantRootedMixin, TemplateView):
def get_context_data(self, **kwargs):
d = super(ServiceList, self).get_context_data(**kwargs)
d['services'] = Services.objects.all()
d['current_company'] = self.context.company.id
return d
def form_valid(self, *args, **kwargs):
return super(ServiceList, self).form_valid(*args, **kwargs)
This view works in the sense that it shows all of the relevant information (with the checkboxes). If I change the query to filter the services by 'company id'. the view works as desired as well.
The problems I have revolve around the fact that pressing 'save'. crashes the program, throwing the following error.
'super' object has no attribute 'post'
Our program works mostly through generic classbased views and modelforms, so we have relativly limited experience with creating our own custom solutions. By my own estimation the problem seems to be twofold:
The view is probably not configured right to process the 'post' data
It is questionable if the data will be processed to the database afterwards.
Though are 'sollution' is currently flawed, are we looking in the right direction? Are we on the right way to solve our problem?
Regards
I believe you are on the right track. What I would suggest is to not be afraid to move away from generic views and move toward a more custom solution (even if you are inexperienced with it.)
The first routine that comes to my mind would be as follows:
gather all the id's that were checked by the user into a list from request.POST
Update the appropriate object's M2M field to contain these new id's.
Save the fore-mentioned object.
[Edit]
One thing I have trouble with is gathering the ID' s from the request.POST. Could you provide me with an example on how to do this?
Sure, from your HTML file I see you are creating inputs with name=service. That leads me to believe you could do something like:
ids = request.POST.get('service')
but to teach you how to fish rather than giving you a fish, you should try to simply:
print request.POST.items()
This will return and print to the console everything that was posted from your form to your view function. Use this to find out if you are getting a list of id's from the template to the server. If not, you may have to re-evaluate how you are building your form in your template.
Your first point is correct: TemplateView has no "post" method defined and that is why you get the error message when you call super().form_valid. You must either define it yourself or use a CBV which has a post method that you can override (e.g. UpdateView)
And I also believe that your second point is correct.
You would need to use an UpdateView to use the built in functionality (or CreateView).
I had a similar problem to solve (selecting values from many-to-many fields in the front-end) and I ended up with doing it "by hand" because I could not get it to work with CBV. "by-hand" => parse the values from the form, update the database, return HttpResponse
You might want to look at ModelFormSets:
https://docs.djangoproject.com/en/1.11/topics/forms/modelforms/#model-formsets
Hope this helps!
Alex

Django Problem - trying to access data entered into a form and feed it through a different page

OK, so let me give you an overview first. I have this site and in it there is a form section. When you access that section you can view or start a new project. Each project has 3-5 different forms.
My problem is that I don't want viewers to have to go through all 3-5 pages to see the relevant information they need. Instead I want to give each project a main page where all the essential data entered into the forms is shown as non-editable data. I hope this makes sense.
So I need to find a way to access all that data from the different forms for each project and to feed that data into the new page I'll be calling "Main". Each project will have a separate main page for itself.
I'm pretty much clueless as to how I should do this, so any help at all would be appreciated.
Thanks
You could try this. After that, you could:
Try creating a model for each project. This is done in "models.py" of the application modules created by django-admin
Use views to show that data to people (on your Main page)
If you've already seen all that, then:
First, you should create a view for your main page. So if you have an application my_app, my_app/views.py should be like:
def main_page_view(request, project_name):
# Your code here
pass
Then, to use this, you'd modify urls.py and add in something like:
(r'^projects/(?:<project_name>[a-zA-Z0-9]+)', 'my_app.views.main_page_view'),
Also, you'd need models, which are created in models.py, by subclassing django.models.Model
EDIT: re-reading your question, I guess you need this
Data can be passed from a view to a template through the context.
So say you create a summary view...
def summary(request, *args, **kwargs):
In that view you can query the database using the model api and pass the result of that query into the template for rendering. I'm not sure what your models look like, but say you had a model that had a title and the owner (as a ForeignKey to user)...
class Project(models.Model):
title = models.CharField(max_length=250)
user = models.ForeignKey(User)
Your model will be obviously be different. In your view you could query for all of the models that belong to the current user...
def summary(request, *args, **kwargs):
projects = Project.objects.filter(user=request.user)
Once you've gathered that, you can pass in the query to the template rendering system...
def summary(request, *args, **kwargs):
projects = Project.objects.filter(user=request.user)
render_to_response('project_summary.html', {'projects': projects }, ... )
When you pass the query to the template, you've named it projects. From within the template you can access it by this name...
<body>
<table>
{% for project in projects %}
<tr><td>{{ project.title }}</td></tr>
{% endfor %}
</table>
</body>
(Notice also how you can access a property of the model from within the template as well.)