I'm trying to get the name of a model in my template so i can give it a different design in the template
#views.py
class PostListView(ListView):
model = Post
template_name = 'blog/home.html'
context_object_name = 'posts'
paginate_by = 15
def get_queryset(self):
posts = []
shared_post = []
if self.request.user.is_authenticated:
user_id = self.request.user.id
view_user_post = Post.objects.filter(user=self.request.user)
user_profile = User.objects.get(id=user_id).profile
# print(user_profile)
for profile in user_profile.follower.all():
for post in Post.objects.filter(user=profile.user):
posts.append(post)
for profile in user_profile.follower.all():
for share in Share.objects.filter(user=profile.user):
shared_post.append(share)
chain_qs = chain(posts, view_user_post, shared_post)
print(chain_qs)
return sorted(chain_qs, key=lambda x: x.date_posted, reverse=True)
else:
posts = Post.objects.all().order_by('?')
return posts
#models.py
class Share(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
post = models.ForeignKey(Post, on_delete=models.CASCADE)
content = models.TextField(max_length=140, null=True, blank=True)
date_posted = models.DateTimeField(default=timezone.now)
def __str__(self):
return '{}- {}'.format(self.post.title, str(self.user.username))
class Post(models.Model):
title = models.CharField(max_length=140)
content = models.TextField(validators=[validate_is_profane])
likes = models.ManyToManyField(User, related_name='likes', blank=True)
date_posted = models.DateTimeField(default=timezone.now)
user = models.ForeignKey(User, on_delete=models.CASCADE)
image = models.ImageField(upload_to='post_pics', blank=True)
image_2 = models.ImageField(upload_to='post_pics', blank=True)
image_3 = models.ImageField(upload_to='post_pics', blank=True)
restrict_comment = models.BooleanField(default=False)
saved = models.ManyToManyField(User, related_name='saved_post', blank=True)
I need a way to check the name of the model in the template possibly an if/ else statement to check properly. thanks
What about create a function inside your model that will return the name of the model?
Inside your models.py for each model:
def get_my_model_name(self):
return self._meta.model_name
Inside your template then yo can do something like:
{%if post.get_my_model_name == 'post'%}
Do something ...
Instead of checking the model name I suggest you implement a boolean property in each model that returns True in one case and False in the other one. For example:
class Post(models.Model):
# whatever fields and methods
#property
def is_shared(self):
return False
class Share(models.Model):
# whatever fields and methods
#property
def is_shared(self):
return True
Then in your template just check {% if post.is_shared %}
Related
I have a listview where I'm trying to filter out products by category. Some products have a subcategory. When a product has a subcategory I want the listview to display them by subcategory.
Problem is: The listview works perfect for items with a subcategory, but does not work for items who do not have a subcategory. Where am I taking a wrong turn here?
Models:
class Category(models.Model):
category_name = models.CharField(max_length=200)
sub_category = models.CharField(max_length=200,blank=True,null=True)
category_picture = ResizedImageField(upload_to='category/', null=True, blank=True)
category_info = models.TextField(blank=True, null=True)
category_video = models.CharField(max_length=250,blank=True, null=True)
def __str__(self):
if self.sub_category is None:
return self.category_name
else:
return f" {self.sub_category}"
class Meta:
ordering = ['category_name']
class Bottle(models.Model):
category_name = models.ForeignKey('Category', on_delete=models.SET_NULL,null=True,blank=True)
brand = models.ForeignKey('Brand', on_delete=models.CASCADE)
bottle_name = models.CharField(max_length=255)
bottle_info = models.TextField()
bottle_tasting_notes = models.TextField()
bottle_barcode = models.IntegerField()
bottle_image = ResizedImageField(upload_to='bottles/',null=True, blank=True)
bottle_shop_link = models.CharField(max_length=250, null=True, blank=True)
def __str__(self):
return f"{self.brand}, {self.bottle_name}"
class Meta:
ordering = ['bottle_name']
View:
class BottlesByCategoryView(ListView):
model = Bottle
context_object_name = 'bottles'
#Filter bij subcategory in the category model. If no subcategory exists, load by category_name
def get_queryset(self):
if Bottle.objects.filter(category_name__sub_category=self.kwargs['category']) is None:
return Bottle.objects.filter(category_name__category_name=self.kwargs['category'])
else:
return Bottle.objects.filter(category_name__sub_category=self.kwargs['category'])
def get_context_data(self, **kwargs):
context = super(BottlesByCategoryView, self).get_context_data(**kwargs)
if Bottle.objects.filter(category_name__sub_category=self.kwargs['category']) is None:
context['category_info'] = Category.objects.filter(category_name=self.kwargs['category'])
else:
context['category_info'] = Category.objects.filter(sub_category=self.kwargs['category'])
return context
URLS:
path('BottlesByCategory/<str:category>/',BottlesByCategoryView.as_view(template_name='academy/bottlesByCat_list.html'),name='bottlesByCat_list'),
Can i not use if statements in the get_context_data and get_query_set?
So I am trying to figure out why my dropdown menu will not display the list of collections for the user to pick from.
Form Screenshot: [1]: https://i.stack.imgur.com/UIrq6.png
Here is the Form.py file class used for this problem:
class ProductForm(ModelForm):
class Meta:
model = listing
fields = 'all'
_---------------------------------------------
Here is the user form VIEW:
def index(request):
form = ProductForm
if request.method == 'POST':
form = ProductForm(request.POST)
if form.is_valid():
form.save()
context = {'form':form}
return render(request, 'index.html', context)
Here is also the code for the 2 models here:
class Collection(models.Model):
title = models.CharField(max_length=255)
def __str__(self) -> str:
return self.title
class Meta:
ordering = ['title']
class listing(models.Model):
image = models.ImageField(blank=True, null=True)
name = models.CharField(max_length=255)
description = models.TextField()
unit_price = models.DecimalField(max_digits=6, decimal_places=2, validators=[MinValueValidator(1)])
inventory = models.IntegerField()
last_update = models.DateTimeField(auto_now=True)
collection = models.ForeignKey(Collection, on_delete=models.PROTECT, blank=True, null=True)
vendors = models.ForeignKey(User, on_delete=models.CASCADE, null=True, blank=False)
I'm somewhat new to django and just trying to understand why for the form it won't display the list of collections in the dropdown.
I want to have a url pattern that takes 2 slugs. I'm trying to make it look like http://127.0.0.1:8000/category/model but I'm having difficulties understanding how to do this.
Below is what I have so far:
models.py
def model_detail_view(request, category_slug, model_slug):
model = Model.objects.get(
category__slug=category_slug, model_slug=model_slug)
context = {
"model": model,
}
return render(request=request, template_name='main/model_detail.html', context=context)
urls.py
path("<str:category_slug>/<str:model_slug>/", views.model_detail_view, name="model_detail_view"),
models.py
class Category(models.Model):
title = models.CharField(max_length=50)
featured_image = models.ImageField(upload_to="categories")
category_slug = AutoSlugField(null=True, default=None,
unique=True, populate_from='title')
class Meta:
verbose_name_plural = "Categories"
def __str__(self):
return self.title
class Model(models.Model):
title = models.CharField(max_length=80)
category = models.ManyToManyField(Category)
featured_image = models.ImageField(upload_to=image_dir)
model_slug = AutoSlugField(null=True, default=None,
unique=True, populate_from='title')
class Meta:
verbose_name_plural = "Models"
def __str__(self):
return self.title
Try this,
model = model = Model.objects.get(category__category_slug=category_slug, model_slug=model_slug)
Reference:
Django:Lookups that span relationships---(Django Doc)
I'm looking for a way to bring data from one model into a view of another model for a ListView. Basically, when the user opens up the listview of the vocabulary model, I need to look up and pull out the associated pinyin field from the dictionary model by using the vocab field. There is some example code at the bottom of the codeview that would be how I would match up a Vocabulary.vocab with a Dictionary.pinyin.
############### Models
class Vocabulary(models.Model):
created_by = models.ForeignKey(User, on_delete=models.CASCADE)
vocab = models.CharField(max_length=255, blank=False, null=False)
translation = models.CharField(max_length=255, blank=False, null=False)
level = models.PositiveSmallIntegerField(blank=True, null=True, choices=LEVELS, default=0)
audio = models.URLField(blank=True, null=True)
objects = RandomManager()
class Meta:
constraints = [
models.UniqueConstraint(fields=['created_by', 'vocab'], name='User Vocab Duplicate Check')
]
verbose_name = "Chinese Vocabulary"
verbose_name_plural = verbose_name
# this function will be invoked when this model object is foreign key of other model(for example Employee model.).
def __str__(self):
return self.vocab
class Dictionary(models.Model):
traditional = models.CharField(max_length=20)
simplified = models.CharField(max_length=20)
pinyin = models.CharField(max_length=255)
simplified_radical = models.CharField(max_length=20)
hsk_level = models.PositiveSmallIntegerField(blank=True, null=True, choices=LEVELS, default=0)
frequency_rank = models.PositiveIntegerField(blank=True, null=True)
phrase_url = models.CharField(max_length=200)
radical_url = models.CharField(max_length=200)
definition = models.TextField()
objects = RandomManager()
class Meta:
verbose_name = "Dictionary"
verbose_name_plural = "Dictionary"
def __str__(self):
return self.simplified
################# Views
class VocabDetailView(LoginRequiredMixin, DetailView):
model = Vocabulary
template_name = 'library/vocab_details.html'
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['dictionary'] = Dictionary.objects.get(simplified=self.object.vocab)
return context
class VocabListView(LoginRequiredMixin, ListView):
model = Vocabulary
template_name = 'library/vocab_list.html'
paginate_by = 50
def get_queryset(self):
return Vocabulary.objects.filter(created_by=self.request.user)
'''
hao = Vocabulary.objects.get(vocab='你')
haodict = Dictionary.objects.get(simplified=hao.vocab)
haopin = hao_dict.pinyin
'''
If you objects were related, you could override the get_queryset to use select_related or similar in order to get the related objects. But it doesn't look like you can do that because the objects aren't related.
So you could either not use a ListView and gather your objects in the context, or override the context to get the Dictionary objects you want. Sounds like you'd do something like;
def get_context_data(**kwargs):
context = super().get_context_data(**kwargs)
dicts = Dictionary.objects.filter(pinyin__in=self.object_list.values_list('vocab', flat=True))
context['dictionaries'] = dicts
return context
I am creating a wiki and need to put in values in the model called revision. This table has a foreigkey to wikipage.
My problem is that I am unable to insert values in the revision model.
I have tried using def form_valid(self, form) like you would when entering user, without any luck.
Models.py
class Wikipage(models.Model):
title = models.CharField(max_length=100)
date_created = models.DateTimeField('Created', auto_now_add=True)
def __str__(self):
return self.title
class Meta:
verbose_name_plural = "Wikipages"
class Revision(models.Model):
wikipage = models.ForeignKey(Wikipage, null=True, on_delete=models.CASCADE, related_name='revisions')
content = models.TextField('Content')
author = models.ForeignKey(User, null=True, on_delete=models.SET_NULL)
last_edit = models.DateTimeField('Last Edited', auto_now=True)
comment = models.TextField('Comment', blank=True)
class Meta:
verbose_name = 'Revision'
verbose_name_plural = 'Revisions'
ordering = ['-last_edit']
get_latest_by = ['last_edit']
def __str__(self):
return self.content
View.py
Class WikipageCreateView(CreateView):
template_name = 'wiki/wikipageform.html'
model = Wikipage
fields = ['title']
def form_valid(self, form):
form.instance.author = self.request.user
return super().form_valid(form)
The template are as simple as possible with {{ form.as_p }} and all the necessary stuff.