Django: 1 view for different users? - python

In my project, I'd like to split pages between a side menu and a content page.
I'd like to show a sidemenu which is different for user types (there are 5 user types, so there will be 5 sidemenus). But sometimes, the content page to display can be the same for these 5 user types.
I was looking for a "pattern" to handle this, I thought about one, but never seen it in another project. I'd like you to tell me if it's a good or bad practice:
1 URI for all user types (eg. /myapp/display_home)
In views.py, 1 view for all user types. Into the view, I try to know if the user is logged in, and then which type of user we are dealing with. Then, redirect to the HTML, passing in context a variable containing the user type.
In the end, in the template, something like this:
Example of template:
{% if user_type == "anonymous" %}
<!-- display anonymous sidemenu here -->
{% elif user_type == "landlord" %}
<!-- display landlord sidemenu here -->
{% endif %}
<-- Here is the same content for all user types -->
Do you have any suggestion? another pattern to propose?

Check this answer for discussion on user.is_authenticated. You can also check within the view to see who the user is (see here) and modify the context being sent to the template accordingly. Another option would be to modify your view to simply show different types of users different templates.
Lots of ways to accomplish this, not sure if there's a "correct" one.
Your comment made me realize that this is exactly what the Groups feature of the auth package is for. You can assign users to groups, query whether they're a member of the group, and then show content based on that. I apologize that I don't have time to write out sample code, but there's tons of stuff here on SO about it; hopefully that's a good starting point for you.

I don't know if it is good style. But you could use
{% include user_type_sidemenu_template with arg1=... %}
in your template and provide different templates for the sidemenu for each user_type. You can then set the template variable user_type_sidemenu_template to the corresponding template name in your view.

Related

How to make a button in html that can trigger backend functions in Python?

It may seem like I have no idea what I'm doing - which is absolutely correct. Doing a project in which we're pretty much thrown to the wolves. I have never learned HTML, or used any frameworks. Also not too familiar with Python.
The following code is meant to show a list of question titles - when you click on them, you get redirected to a page showing the question, additional text, and various answers.
I want to insert buttons that let you upvote these questions, and each one should be right next (at least close) to the question. When clicked: in the frontend, I only want some visual signal that the user has upvoted, like the button turning orange (so original), or green, whatever. In the backend, I want the button to trigger a static method called vote(question, user), which creates a vote object, to record that the user has upvoted a question. These objects are stored in a database. They contain nothing more but their own auto-generated IDs, the voter/user's ID, and the relevant question's ID.
Ideally, I want the color of the button to depend on the existence of this vote object, but that is really just extras.
And if possible, I want a number to be displayed next to the question, showing the number of votes it has received. To get the num of votes, it should invoke question.get_votes(self), which counts all vote objects that contain the question's ID. I do realize that I could just store this as an attribute with the question and let it increase each time someone voted, but... yeah.
I do not know if arguments are required, and I really don't have a clue on how I'm supposed to do this, even after looking at other threads/googling around.
<ul>
{% for question in all_questions_with_sub_code %}
<!-- no idea what i'm supposed to enter here -->
<li>{{question.question_title}}</li>
{% endfor %}
</ul>
You need to use combination of Django + Ajax to create smooth voting system without page reload.
The following link will get you started:
My Own Like Button: Django + Ajax -- How?
Create your button on HTML and handle the click in JS. Pass the arguments required to Python using AJAX like:
$.ajax({
method: 'POST',
url: 'someURL',
data: {'key': value,
csrfmiddlewaretoken:$('input[name=csrfmiddlewaretoken]').val()},
success: function (data) {},
error: function (data) {}
});
Then receive it in Python like this:
def convert(request):
if request.is_ajax():
request_data = request.POST
return HttpResponse(1)
Make sure you handle URL and use CSRF_TOKEN in your HTML

Django: Python variable data as background image

Details and Problem:
I am making a website which uses steam's social authentication and API, it saves users data in the database, and makes the session cookie that contains two main data, username and logged in cookies.
The data which the variable contains is the url to the image, which leads me to the problem, i want to show the picture of user on the index page, but css static file would not allow me to use the variable.
so i tried some other options:
Using HTML <style> tag:
<a class="profile_picture" href="/profile" style="background-image: url({{ picture }})"></a> # would not work, as it takes every character as string.
Using HTML <img> tag:
<img class="profilepicture" src="{{ picture }}"></img> # same problem here, takes every character as unicode string.
Question:
Is there any other way to do this with the setup i have? ( Django, CSS, HTML, Python ), i am trying to do this without installing something extra, i have seen sass, but is there still any other possible way?
Can i use <style> or <img> tag to take variable url as background image?, if so how?
It's hard to answer this question without all of the details, but the first issue that comes to mind is that you are most likely referencing your context variable "picture" incorrectly. Again, I'm not sure by your question what exactly you are doing, but perhaps this example will help:
If I have a model named "Person" and that model has 2 fields, "name" and "picture". In my views.py, if I had a function called main:
def main(request):
persons = Person.objects.all()
return render(request, index.html, {"persons":persons } )
This function creates an context variables named persons that will be available in your index.html file. Obviously this is a very loose example, but serves to guide you with the basics. So in your index.html template, you would reference the picture field by doing this:
{% for person in persons %}
{{ person.picture }}
{% endfor %}
Hope that helps.

How to use <select> information in django form

So I have my django project which includes a HTML page that shows a list and a submit button.
I want to use the submit button to send the selected item ID to the server and than use it.
That`s my code :
<form>
<select>
{% for item in list %}
<option value={{item.name}}>{{ item.name }}</option>
{% endfor %}
</select>
<input type="submit"/>
</form>
The things I want to know are :
What to write in the action of the form so it will only reload the page.
How to enter the form data into a view.
As i understand, you want to take the value on your select and do something with it in the server.
I would advise you to read the documentation, as it is pretty detailed about what you need to know to work with forms. You should also read a little about forms, as you are missing a couple details.
Now, the action must point to one of your urls. Your url must be pointing to a view and in your view, if everything is ok, you should be getting a request object.
Depending on your post method, you have a python dictionary in request.GET or request.POST, filled with the values in your form.
That is assuming you are using your form created from scratch. In django you can use the Form class, which creates the html (or lets you create it, but giving you some constraints), validates the form, saves the form to a model (in the case it is a ModelForm). It is a valuable class for me and prefer it over working with raw html.
Also, assuming you haven't, i strongly advice you to go through the getting started. Even if it keeps things basic, it does a good job at introducing core django modules.

Validating a user site-wide with Django's auth system

How can I display content side-wide (on every page) based on if the user is logged in or not? I have a sidebar area defined in my base.html which is either populated with login/register forms (if the user is not logged in) or a dashboard (if the user is logged in).
How can I make this universal to every single web page on my site? Do I have to manually check the user each time a new view is called and pass a user variable to my render_to_response()? There's got to be a simpler way.
I don't think there are a system wide solution if I understood you right. You have to verify each page based on whether the user is authenticated or not.
In the template you add the following code to see whether the user is a valid and authenticated. And you have to do so for each template with user level contents.
{% if user.is_authenticated %}
... html stuff ...
{% endif %}
Another idea maybe is to use decoration #login_required. However you would still need to add it to each view with user level contents.

How to generate lots of redundant ajax elements like checkboxes and pulldowns in Django?

I've been getting lots of answers from stackoverflow now that I'm in Django just by searching. Now I hope my question will also create some value for everybody.
In choosing Django, I was hoping there was some similar mechanism to the way you can do partials in ROR. This was going to help me in two ways. One was in generating repeating indexed forms or form elements, and also in rendering only a piece of the page on the round trip.
I've done a little bit of that by using taconite with a simple URL click but now I'm trying to get more advanced. This will focus on the form issue which boils down to how to iterate over a secondary object.
If I have a list of photo instances, each of which has a couple of parameters, let's say a size and a quantity. I want to generate form elements for each photo instance separately. But then I have two lists I want to iterate on at the same time.
Context:
photos : Photo.objects.all()
and
forms = {}
for photo in photos:
forms[photo.id] = PhotoForm()
In other words we've got a list of photo objects and a dict of forms based on the photo.id.
Here's an abstraction of the template:
{% for photo in photos %}
{% include "photoview.html" %}
{% comment %}
So here I want to use the photo.id as an index to get the correct form. So that each photo has its own form. I would want to have a different action and each form field would be unique. Is that possible? How can I iterate on that? Thanks!
Would it be a with? In Python of course it's form = forms[photo.id] but here?
{% endcomment %}
Quantity: {{ oi.quantity }} {{ form.quantity }}
Dimensions: {{ oi.size }} {{ form.size }}
{% endfor %}
What can I do about this simple case. And how can I make it where every control is automatically updating the server instead of using a form at all?
Thanks!
James
I'm not sure I understand your question, but here's what I think you want, expressed in pseudo-code:
for photo in photos:
form = forms[photo.id]
generate_some_html(photo, form)
Probably the best way to achieve this is with inclusion tags: http://docs.djangoproject.com/en/dev/howto/custom-template-tags/#inclusion-tags . Basically, it's a custom tag that relies on another template, similar to an RoR partial. The details can be found in the link I provided, but what you basically need to do is
create a package names "templatetags" in one of your app directories
create a module in that package. Let's take foo_tags.py for example.
Add the following boilerplate to foo_tags.py:
from django import template
register = template.Library()
Write your custom tag, which implements generate_some_html. Make it take the caller's context:
#register.inclusion_tag('relative/path/to/some/template.html', takes_context=True)
def foo_tag(context):
photo = context['photo'] # loop variable in parent template
form = context['forms'][photo.id]
# further computation that you need in order to setup the
# context for relative/path/to/some/template.html can be
# done here...
return locals()
Use the context returned by foo_tag in relative/path/to/some/template.html.
Add {% load foo_tags %} to the parent template. You should probably put this near the top, the same way you put imports near the top of a .py file.
Use your new custom tag in the parent template:
{% for photo in photos %}
{% foo_tag %}
{% endfor %}
Django doesn't comme with backed AJAX like RAIL, but it let you choose any lib you want to use from the start.
You can do what you want by creating custom widgets and using form media.

Categories