How to Create Buttons for not Null fields only in Django? - python

I'm fairly new to Django and couldn't find a way to do this yet. I have a model like this:
class Profile(models.Model):
user = models.OneToOneField("User", on_delete=models.SET_NULL, null=True)
user_name = models.CharField(max_length=50)
linkedin = models.URLField(max_length=254, null=True, blank=True)
instagram = models.URLField(max_length=254, null=True, blank=True)
spotify = models.URLField(max_length=254, null=True, blank=True)
On my HTML, I have buttons for each social media field, but I don't want to show them if they are null. How can I create a for loop that will loop through the social media fields only and create buttons for only not null fields?

If your links aren't in a for loop in your HTML. I suggest you to use if block for every social media link.
example is:
{% if profile.linkedin %}
LinkedIn
{% if profile.spotify %}
Spotify
{% else %}
{% endif %}

Related

How can i make good models for categories in django?

im trying to make an online menu. i want to make a category, sub category and items that goes in one of those.
I mean, an item can be on a category like "sushi" -> nameofsushi, or be in a sub category like sushi -> avocado rolls -> nameofsushi.
i have something like this in my models.py but is there a better way to do it?
class Category(models.Model):
name = models.CharField(max_length=200)
description = models.TextField(max_length=500, verbose_name='DescripciĆ³n', blank=True, null=True)
parent = models.ForeignKey('self', related_name='children', null=True, blank=True, on_delete=models.CASCADE)
def __str__(self):
return 'Category: {}'.format(self.name)
class MenuItem(models.Model):
name = models.CharField(max_length=200)
image = models.ImageField(upload_to='menu_images/', null=True, blank=True)
description = models.TextField(blank=True, null=True)
price = models.DecimalField(max_digits=6, decimal_places=0)
other_Price = models.DecimalField(max_digits=6, decimal_places=0, null=True, blank=True)
categories = models.ManyToManyField('Category', related_name='item', null=True, blank=True)
def __str__(self):
return 'MenuItem: {}'.format(self.name)
You need to carefully think about your model design. The way you have designed categories allows you to have unlimited sub-categories. Do you really need that flexibility? Because it comes at the cost of complexity. Think about how you will be interacting with the models.
With your current design, it would be challenging to render in a Django template without preprocessing it in Python using some gnarly recursion, because you have no way apriori to know how many nested sub categories you have. You could have sub-category, sub-sub-category, sub-sub-sub-category and so on.
Also, querying your models will be complicated. Say you have 'Cat1'->'Sub-cat1'->'Sub-sub-cat1'->'menuitem1'. How do you find all menu items that are a descendant of 'sub-cat1'? All I can think of is MenuItem.objects.filter(parent__parent=subcat1_obj). Not very Pythonic or clear to a reader. And you run into problems as you dont know how many layers of sub-categories you have.
Or how do you get just the menu categories? Category.objects.filter(parent=None). Its not obvious from this code what we are talking about.
I would, if your use-case allows it, simplify your model design in this way:
class MenuCategory(models.Model):
category = models.ForeignKey(Category, ...)
...
class MenuSubCategory(models.Model):
menu_category = models.ForeignKey(MenuCategory, ...)
...
class MenuItem(models.Model):
menu_categories = models.ManyToManyField(MenuCategory, ...)
menu_subcategories = models.ManyToManyField(MenuSubCategory, ...)
...
Now rendering your models in a template would be straight forward (given context['menu_categories'] = MenuCategory.objects.all()):
{% for cat in menu_categories %}
{% for item in cat.menuitem_set.all %}
{{ item }}
{% endfor %}
{% for subcat in cat.menusubcategory_set.all %}
{% for item in subcat.menuitem_set.all %}
{{ item }}
{% endfor %}
{% endfor %}
{% endfor %}
Now querying your models will also be more clear. You could also if needed add a Menu model and have different menus.

Custom User PK (Primary Key) - Django - Python

I built a website with Python Django and part of it displays lines of already input data with the primary key next to it. Now I have separate user data by using a foreign key field in each one of my models and the specific user's data is only shown to that logged in user except that all the data regardless of the user is saved in one spot with the model shown in the admin interface(because I'm using foreign keys to separate data). My problem is that I need to display the primary key of just the logged-in user. Take this, for example, if User1 adds 1 line of data to their page then User2 adds 1 line of data on their page which will appear separate from one another, then User1 uploads another line of data, Then I user traditional primary key to number the data lines of User1 the numbers will be 1 and three instead of keeping them in numerical order of 1 and 2 and disregarding User2's data in the counting of the data. It's as if I need a separate primary key for each user. Sorry this is really hard to explain. I have found a temporary solution of using {{ forloop.revcounter }} to count in a for loop instead of using the primary key but the problem with this is that when data is deleted all the numbers above it go down one because this tag just counts how many times the for loop has looped. I have found no information of the internet about this and how to solve it beyond this. I might just be looking in the wrong places but I need help. Thanks!
EDIT:
models.py
class Sheet_Extinguisher(models.Model):
user = models.ForeignKey(User, default=True, related_name="Extinguisher", on_delete=models.PROTECT)
floor = models.CharField(max_length=5, choices=FLOOR_LEVEL_FE, blank=True, null=True, verbose_name='Floor / Level')
area_room = models.CharField(max_length=35, blank=True, null=True, verbose_name='Area / Room')
building_address = models.CharField(max_length=46, choices=BUILDING_ADDRESS, blank=True, null=True, verbose_name='Building and Address')
type = MultiSelectField(choices=TYPE_FE, blank=True, null=True, verbose_name='Type')
size = models.CharField(max_length=3, choices=SIZE_FE, blank=True, null=True, verbose_name='Size')
hydrostatic_date = models.DateField(blank=True, null=True, verbose_name='Last Hydrostatic Test')
mass_notes = models.CharField(max_length=20, blank=True, null=True, verbose_name='Mass Fire Tech Notes')
notes = models.TextField(max_length=500, blank=True, null=True, verbose_name="Inspector's note")
class Meta:
ordering = ['building_address']
def __str__(self):
return self.building_address or 'None'
def get_absolute_url(self):
return reverse('list_extinguisher')
HTML (with pk):
{% if filter.qs %}
{% for post in filter.qs %}
<tr>
<td><div class="item1" style="text-align: center;">{{ post.pk }}</div></td>
{% endfor %}
{% endif %}
HTML (just with forloop counter):
{% if filter.qs %}
{% for post in filter.qs %}
<tr>
<td><div class="item1" style="text-align: center;">{{ forloop.revcounter }}</div></td>
{% endfor %}
{% endif %}

Rendering blank ImageFields in Django template

I am trying to render an instance of this model in my template:
class Candidate(models.Model):
UserID = models.ForeignKey(User, on_delete=models.CASCADE)
ElectionID = models.ForeignKey(Election, on_delete=models.CASCADE)
Bio = models.CharField(max_length=500, blank=True)
Poster = models.ImageField(upload_to="profilepics/", null=True, blank=True)
I am having trouble with rendering the Poster attribute which, as you can see, has the option of being blank.
When I try to render the following html in the template:
<h1>{{candidate.UserID.first_name}} {{candidate.UserID.last_name}} ({{candidate.UserID.username}})</h1>
<h2>{{candidate.ElectionID}}</h2>
<img src="{{candidate.Poster.url}}" width=240><br>
I get an error if Poster is blank.
ValueError: The 'Poster' attribute has no file associated with it.
How do I prevent this error? I want to show nothing if Poster is blank and obviously show the image if it isn't.
Use an if condition.
<h1>{{candidate.UserID.first_name}} {{candidate.UserID.last_name}} ({{candidate.UserID.username}})</h1>
<h2>{{candidate.ElectionID}}</h2>
{% if candidate.Poster %}
<img src="{{candidate.Poster.url}}" width=240>
{% endif %}
<br>

How to display different custom users after logging in Django

I have 2 custom users, student and teacher. I want that if student is logged in, a particular message is displayed, otherwise if teacher is logged in, another message to show.
{% if request.user.is_authenticated %}
{% if user is student %}
<p>Welcome, {{ user.student.surname }} Thanks for logging in.</p>
{% else %}
{% if user is teacher%}
<p>Welcome, {{ user.teacher.surname }} Thanks for logging in.</p>
{% endif %}
{% endif %}
class User(AbstractUser):
pass
class Student(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE, primary_key=True)
name = models.CharField(max_length=30, null=True, blank=True, default=None)
surname = models.CharField(max_length=50, null=True, blank=True, default=None)
class Teacher(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE, primary_key=True)
name = models.CharField(max_length=30, null=True, blank=True, default=None)
surname = models.CharField(max_length=50, null=True, blank=True, default=None)
email = models.EmailField(unique=True, null=True, blank=True, default=None)
User.student = property(lambda p: Student.objects.get_or_create(user=p)[0])
User.teacher = property(lambda p: Teacher.objects.get_or_create(user=p)[0])
First, I believe it's not a really good idea to have user.teacher and user.student as a property for two reasons:
1. I assume that a user can be either a student or a teacher, but not both (please correct me if I'm mistaken). You are using get_or_create, so, for instance, if you'll try to access a user teacher property with user being already a student, you will end up in the situation when the user is both a student and a teacher.
2. Django ORM already does this for you: using OneToOneField you can reference Teacher or Student object from your User object as user.teacher or user.student as long as the corresponding User or Teacher exists.
You can use hasattr to check if the given user is a teacher or a student:
class User(AbstractUser):
#property
def is_teacher(self):
return hasattr(self, 'teacher')
#property
def is_student(self):
return hasattr(self, 'student')
Then render your template accordingly:
{% if user.is_teacher %}
# Do teacher-related logic
{% elif user.is_student %}
# Do student-related logic
{% else %}
# This should not be the case, but you may want to display an error message or something
{% endif %}

Show images on Django Non Rel Templates using Google App Engine

I'm doing an app with Django Non Rel on GAE, and i want to show the Profile Image of the user in the template but i can't here is the model:
from django.db import models
from django.contrib.auth.models import User
# Create your models here.
class userProfile(models.Model):
def url(self, filename):
url = "MultimediaData/Users/%s/%s"%(self.user.username, filename)
return url
user = models.OneToOneField(User)
email_public_user = models.EmailField(blank=True, null=True)
url_user = models.CharField(max_length=200, blank=True, null=True)
company_user = models.CharField(max_length=200, blank=True, null=True)
position_user = models.CharField(max_length=200, blank=True, null=True)
photo_user = models.ImageField(upload_to=url)
def __unicode__(self):
return self.user.username
For now i'm adding the photo via admin to see if i can show the image, here is the template
<div class="navbar-header nav-img">
{% if user.get_profile.photo_user %}
<img class="navbar-brand" src="{{user.get_profile.photo_user}}">
<p class="navbar-brand">{{user.get_username}}</p>
{% else %}
<img class="navbar-brand" src="/media/img/principal_html/img1.png">
<p class="navbar-brand">{{user.get_username}}</p>
{% endif %}
It shows the username, but not the image, i put the user.get_profile.photo_user in a and i got this
ahRkZXZ-c29mdHN5c3RlbWFuYWdlcnIiCxIVX19CbG9iVXBsb2FkU2Vzc2lvbl9fGICAgICAzKYKDA/MultimediaData/Users/[username]/img.jpg
There's no view yet because im uploading the image using the django admin and when i save the user with his photo shows the same url
How can i solve this? I need to show the image...plz help

Categories

Resources