I'm trying to build a recipe app that allows users to upload images and save recipes in a list.
The problem I'm facing is when the user doesn't upload an image, I get error: attribute has no file associated with it.
Error
I've looked in Django documentation & tried using default tag in my HTML template with no success.
The value is named image_ingredients in models.py
How could I make it so the user can just leave the ImageField empty?
Here is my code:
models.py
# Recipe Field
class Recipe(models.Model):
title = models.CharField(max_length=200)
# TODO: Add default image if image is left blank
image = models.ImageField(upload_to='recipes/images/', blank=True)
category = models.ForeignKey(Category, on_delete=models.CASCADE,)
daily_meals = ['Breakfast', 'Brunch', 'Elevenses', 'Lunch', 'Tea', 'Supper', 'Dinner']
meal = models.ForeignKey(Meal, limit_choices_to={'name__in': daily_meals}, on_delete=models.CASCADE,)
image_ingredients = models.ImageField(upload_to='recipes/images/', null=True, blank=True)
ingredients = models.TextField(blank=True)
user = models.ForeignKey(User, on_delete=models.CASCADE)
def __str__(self):
return self.title
views.py
# Solo recipe with instructions
def solo(request, recipe_id):
recipe = get_object_or_404(Recipe, pk=recipe_id)
return render(request, 'recipes/solo.html', {'recipe':recipe})
solo.html
<h4>Ingredients</h4>
<img src="{{ recipe.image_ingredients.url }}">
<p>{{ recipe.ingredients }}</p>
You can render the image only when there is an image_ingredients item present, for example:
<h4>Ingredients</h4>
{% if recipe.image_ingredients %}<img src="{{ recipe.image_ingredients.url }}">{% endif %}
<p>{{ recipe.ingredients }}</p>
Related
I am trying to route my Vue home page to the detail page of the specific product with its url when the button is clicked on.
Though my django and vue servers run fine. I get this error in chrome.
Chrome error:
Uncaught (in promise) TypeError: Cannot read properties of undefined (reading 'get_absolute_url')
at Proxy.render (HomeView.vue?43d0:14:1)
at renderComponentRoot (runtime-core.esm-bundler.js?d2dd:893:1)
...
The error only shows up when I add the router link tag with the product.get_absolute_url method. When I take it off, the product items (latestProducts) render fine.
HomeView.vue
<template>
<div class="home">
<div class="product-container">
<div
class="product-item"
v-for="product in latestProducts"
:key="product.id"
>
<img class="prod-img" :src="product.get_image" alt="" />
<h2>{{ product.name }}</h2>
<p>{{ product.price }}</p>
</div>
<div>
<router-link v-bind:to="product.get_absolute_url"
><button>View Item</button></router-link
>
</div>
</div>
<router-view />
</div>
</template>
Here is my models.py file where the get_absolute_url model is defined.
class Product(models.Model):
category = models.ForeignKey(Category, related_name='products', on_delete=models.CASCADE)
name = models.CharField(max_length=255)
slug = models.SlugField()
description = models.TextField(blank=True, null=True)
price = models.DecimalField(max_digits=6, decimal_places=2)
image = models.ImageField(upload_to='uploads/', blank=True, null=True)
thumbnail = models.ImageField(upload_to='uploads/', blank=True, null=True)
date_added = models.DateTimeField(auto_now_add=True)
class Meta:
ordering = ('name',)
def __str__(self):
return self.name
def get_absolute_url(self):
return f'/{self.category.slug} / {self.slug }/'
I have read the django docs that suggest using the reverse() function and the viewname in the views.py to route to the url. But i don't think that would work because I am using the APIView of the rest_framework.
Here is my views.py file:
class ProductDetail(APIView):
def get_object(self, category_slug, product_slug):
try:
return Product.objects.filter(category_slug=category_slug).get(slug=product_slug)
except Product.DoesNotExist:
raise Http404
def get(self, request, category_slug, product_slug, format=None):
product = self.get_object(category_slug, product_slug)
serializer = ProductSerializer(product)
return Response(serializer.data)
I would like to know how to clear this error and/or resources to help understand the url and routing concept better.
I am building a competition website where challenges will be released weekly. For each user I want to track if they have completed a challenge but cannot see how this would be done. Currently the challenges are stored as a model and am using the ListView and DetailView to display them.
from django.db import models
from django.contrib.auth.models import User
STATUS = (
(0, 'Draft'),
(1, 'Publish'),
)
class Challenge(models.Model):
title = models.CharField(max_length=200, unique=True)
slug = models.SlugField(max_length=200, unique=True)
release_date = models.DateTimeField()
preamble = models.TextField()
ciphertext = models.TextField()
plaintext = models.TextField()
status = models.IntegerField(choices=STATUS, default=0)
class Meta:
ordering = ['-release_date']
def __str__(self):
return self.title
Thank you in advance to anyone who helps me with this. Oh and a solution will be submitted and then checked with this form.
<div class='form'>
{% if user.is_authenticated %}
<textarea rows="10" name="plaintext" form="submitAnswer" wrap="soft" placeholder="Plaintext.."></textarea>
<form method="post" id="submitAnswer">
{% csrf_token %}
<input type="submit" value="Submit">
</form>
{% else %}
<p>Must be logged in to submit answer.</p>
{% endif %}
</div>
A really basic implementation is to add a ManyToManyField between your Challenge model and your the User model :
from django.conf import settings
class Challenge(models.Model):
users = models.ManyToManyField(settings.AUTH_USER_MODEL)
# Other fields...
In the above example, you can just activate the relationship if the user has passed the test.
Now, maybe, you want to add informations about this relationship. You can do it with 'through' argument. This model tells if a user has passed the challenge or not and how many tentatives has been done. Modify it as you wish.
from django.conf import settings
class Challenge(models.Model):
users = models.ManyToManyField(settings.AUTH_USER_MODEL,
through='ChallengeUsers')
# Other fields...
class ChallengeUsers(models.Model):
challenge = models.ForeignKey(Challenge, on_delete=models.CASCADE)
users = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
hasPassed = models.BooleanField(default=False)
tentatives = models.IntegerField()
I have a ListView where a I want to list products. The problem is that I can't get the related image of these products as they are in a different model.
The model for products is:
class Product(models.Model):
brand = models.ForeignKey(Brand, on_delete=models.CASCADE, verbose_name='marca')
name = models.CharField('nombre', max_length=40)
description = models.TextField('descripción', blank=True)
price = models.DecimalField(max_digits=8, decimal_places=2)
slug = models.SlugField(max_length=50)
active = models.BooleanField('activo',default=True)
in_stock = models.BooleanField('en stock', default=True)
tags = models.ManyToManyField(ProductTag, blank=True)
date_updated = models.DateTimeField('última actualización', auto_now=True)
The model of images is:
class ProductImage(models.Model):
product = models.ForeignKey(Product, on_delete=models.CASCADE, verbose_name='producto')
image = models.ImageField('imagen', upload_to="product-images")
thumbnail = models.ImageField('miniatura', upload_to="product-thumbnails", null=True)
To get both models in the template I used context.update in the view.
class ProductListView(ListView):
template_name = 'product_list.html'
context_object_name = 'products_list'
model = models.Product
paginate_by = 4
def get_context_data(self, **kwargs):
context = super(ProductListView, self).get_context_data(**kwargs)
context.update({'product_images_list': models.ProductImage.objects.all()})
return context
def get_queryset(self):
tag = self.kwargs['tag']
self.tag = None
if tag != 'all':
self.tag = get_object_or_404(models.ProductTag, slug=tag)
if self.tag:
products = models.Product.objects.active().filter(tags=self.tag)
else:
products = models.Product.objects.active()
return products.order_by('name')
Additionally, I created a filter to iterate both models in a forloop but I think is useless as I don't want to iterate both models, I just want to get the first image that matches the product's FK to show it in the template:
from django import template
register = template.Library()
#register.filter(name='zip')
def zip_lists(a, b):
return zip(a, b)
The template I'm using is:
{% extends 'base.html' %}
{% load humanize %}
{% load product_extras %}
{% block content %}
<div class="destacados">
{% for product, image in products_list|zip:product_images_list %}
<div class="collections coll-watches">
<img class="foto" src="{{ image.thumbnail.url }}">
<p class="prod-description">{{ product.name }}</p>
<p class="prod-description prices"><strong>$ {{ product.price|intcomma }}</strong></p>
<a class="boton-tr boton-tr-watches" href="#">Agregar al carrito</a>
</div>
{% endfor %}
</div>
{% endblock content %}
As you can see the problem is in <img class="foto" src="{{ image.thumbnail.url }}">. I know this is incorrect, but I don't know how to get the image related to the product through its FK.
I'm new i django (only two months) and I'm sure this should be easier, but I can figure it out...
Any help would be appreciated!!
Best regards
you can define a get image url method in your product model as below
def get_image_url(self):
img = self.productimage_set.first()
if img:
return img.thumbnail.url
return img #None
and call it in your templates get_image_url
Thank you very much #bmons. I had to modify the method a little bit, but your answer gave me the clue I needed.
This is the final code:
def get_image_url(self):
img = self.productimage_set.first().thumbnail.url
if img:
return img
return img #None
When Using img = self.productimage_set.thumbnail.first() I get a RelatedManager error.
Anyway, I really appreciate your help!! Cheers
I'm new in Django and I'm developing an app but I'm stuck in this Error.
First I want to apologize for my English since is not my first language and then I hope I'm in the right place to ask for little help.
I'm developing a website about Publication of articles. The page "Publication" return a list of the model instances - in my case all the publications in the db.
What I'm trying to do is to assign a url to each of the instances of my Model, such that the user can click on it and see the page which is populated with other relevant information of that instance.
To do this I'm using get_absolute_url in my template and DetailView in my view.
The list of all the instance works fine but when I click on each of the instance I run the error 'NoneType' object has no attribute '_default_manager' .
I google already and try to follow some guidelines here and there, and try to find solution in Django doc couldnt figure out the solution...
Here my code:
models.py
class Publications(MPTTModel):
code = models.CharField(max_length=50)
title = models.CharField(max_length=150)
date = models.DateField(null=True)
magazine = models.CharField(max_length=50)
country = models.CharField(max_length=30)
slug = models.SlugField(max_length=150)
img01 = models.ImageField(upload_to="photo", blank=True, null=True)
link = models.URLField(max_length=200, blank=True, null=True)
template = models.ForeignKey("Template", related_name="publications", null=True, blank=True)
parent = models.ForeignKey('self', null=True, blank=True, related_name='children')
control_field = models.CharField(max_length=15)
class Meta:
verbose_name_plural = "Publications"
def __unicode__(self):
return self.title
def get_absolute_url(self):
return reverse('mag-publication',args=(self.slug,))
publications.html
{% load mptt_tags %}
{% load sito_tags %}
{% full_tree_for_model myApp.Publications as publications %}
{% for publications,structure in publications|tree_info %}
{% if publications.img01 %}
<div id="title_publication_container">
{{ publications.magazine }}
</div>
{% else %}
....
{% endif %}
{% endfor %}
urls.py
urlpatterns = patterns('',
url(r'^(?P<id_page>\d+)/(?P<slug>[\w-]+)/$', pages,),
url(r'^(?P<id_page>\d+)/(?P<slug_page>[\w-]+)/(?P<id>\d+)/(?P<slug>[\w-]+)/$', projects,),
url(r'^mag-publication/(?P<slug>[\w-]+)/$', PublicationDetailView.as_view() , name='mag-publication'),
)
view.py
class PublicationView(object):
queryset = Publications.objects.all()
class PublicationListView(PublicationView, ListView):
paginate_by = 20
class PublicationDetailView(PublicationView, DetailView):
slug_field = 'slug'
The error show me this Debug informations:
AttributeError at /6/publications/*title_publication*/
**'NoneType' object has no attribute '_default_manager'**
Request Method: GET
Request URL: .../6/publications/*title_publication*/
Django Version: 1.5.4
Exception Type: AttributeError
Exception Value: 'NoneType' object has no attribute '_default_manager'
Exception Location: /home/gabriele/virtual_envs/virt2/lib/python2.7/site-packages/feincms/views/cbv/views.py in get_object, line 20
Python Executable: /home/gabriele/virtual_envs/virt2/bin/python
Maybe the problem has something to do with feincms as it said in the "Exception Location" but everything came out after I tried to work on the instance of the Model.
Thank you for your help.
You probably didn't add feincms.module.page to your INSTALLED_APPS as per the documentation. If you follow the traceback, the error appears in get_object() where it tries to access the page model.
Are you using an older FeinCMS version? Newer versions raise a warning in that case.
Well i don't know for feincms but in your views you have :
class PublicationView(object):
queryset = Publications.objects.all()
class PublicationListView(PublicationView, ListView):
paginate_by = 20
class PublicationDetailView(PublicationView, DetailView):
slug_field = 'slug'
First of all you don't need to set the slug field if his name is already 'slug'.
And an other thing :
You inherit from PublicationView in your PublicationDetailView, but the DetailView need a single object, just try like this in your url file :
url(r'^mag-publication/(?P<slug>[\w-]+)/$', DetailView.as_view(model=Publications) , name='mag-publication')
Off course don't forget to import DetailView and Publications model into your url file.
EDIT 20/08/2014
In your get_absolute_url method you use :
return reverse('mag-publication',args=({'slug':self.slug}))
If you want to use dict for params you must use :
return reverse('mag-publication',kwargs={'slug':self.slug})
And if you want to use args you must do :
return reverse('mag-publication',args=(self.slug,))
I solved part of the problem. I used a combination of get_absolute_url and DetailView.
I can see the perfectly the list of the publications in publication.html but when I click to one of them the app show me - in publications_detail.html - the detail of all the instances of the Model instead only one.
From publications in admin "view on site" it works but there's the same problem, show me all the instances together.
The question is how to catch only one instance. Follow the code :
models.py
class Publications(MPTTModel):
title = models.CharField(max_length=150)
slug = models.SlugField(max_length=150)
img01 = models.ImageField(upload_to="photo", blank=True, null=True)
template = models.ForeignKey("Template", related_name="publications", null=True, blank=True)
parent = models.ForeignKey('self', null=True, blank=True, related_name='children')
control_field = models.CharField(max_length=15)
class Meta:
verbose_name_plural = "Publications"
def __unicode__(self):
return self.title
def get_absolute_url(self):
return reverse('mag-publication',args=(self.slug,))
views.py
class PublicationsDetail(DetailView):
queryset = Publications.objects.all()
template_name = 'website/publications_detail.html'
urls.py
url(r'^mag-publication/(?P<slug>[\w-]+)/$', PublicationsDetail.as_view()
publications_detail.html
{% load mptt_tags %}
{% load sito_tags %}
{% full_tree_for_model napeApp.Publications as publications %}
{% for publications,structure in publications|tree_info %}
{% if publications.img01 %}
<div id="title_publication_container">
{{ publications.magazine }}
</div>
{% else %}
....
{% endif %}
{% endfor %}
In my case I just renamed meta to Meta and it solved.maybe it is related to sensitive capital class name
I am trying to display a list of objects (Images)based on a many-to-many relationship (Image / Gallery with an intermediary Galleryimage model).
Galleryimage has an additional field called position which I want to use to manage the order that the images are listed in a template.
I also have a page model which can optionally have a gallery attached to it.
My models look like this:
class Page(models.Model):
gallery = models.ForeignKey(Gallery, blank=True, null=True)
slug = models.SlugField()
title = models.CharField(max_length=200)
content = models.TextField()
def __unicode__(self):
return self.title
class Image(models.Model):
title = models.CharField(max_length=50)
image = models.ImageField(upload_to='images')
def __unicode__(self):
return self.title
class Gallery(models.Model):
title = models.CharField(max_length=50)
images = models.ManyToManyField(Image, through='Galleryimage')
def __unicode__(self):
return self.title
class Galleryimage(models.Model):
image = models.ForeignKey(Image)
gallery = models.ForeignKey(Gallery)
position = models.IntegerField()
class Meta:
ordering = ['position']
I am retrieving a page model in my view like this:
def detail(request, page_id):
p = get_object_or_404(Page, pk=page_id)
return render_to_response('detail.html', {'page': p},
context_instance=RequestContext(request))
And finally, I am displaying the images in the template like so:
{% block images %}
{% if page.gallery %}
{% for image in page.gallery.images.all %}
<a rel="gallery" href="{{ STATIC_URL }}{{ image.image }}"></a>
{% endfor %}
{% endif %}
{% endblock %}
The images all display as expected however, the order always seems to be the same, regardless of what I do.
Can anyone give me a nudge in the right direction?
Any advice appreciated.
Thanks.
Have you tried to set the ordering option in the Image model? I know you setted the position in the through relation table, but by moving it to the Image model (if possible ?) and setting the order on that model, it shall work.
class Image(models.Model):
title = models.CharField(max_length=50)
image = models.ImageField(upload_to='images')
position = models.IntegerField()
def __unicode__(self):
return self.title
class Meta:
ordering = ['position']