How to upload files based on primary key of foreignkey? - django

Basically I am trying to create an app which can allow user to upload lessons material such as documents on their specific posts. However, I am unsure of how I should display the documents uploaded based on the primary key of the posts. As of now, my posts are displaying all the documents that are being uploaded by the particular user.
This is my 'Post' model
class Post(models.Model):
title = models.CharField(max_length=100)
image = models.ImageField(default = 'default0.jpg', upload_to='course_image/')
description = models.TextField()
price = models.DecimalField(decimal_places=2, max_digits=6)
date_posted = models.DateTimeField(default=timezone.now)
author = models.ForeignKey(User, on_delete=models.CASCADE)
rating = models.IntegerField(default = 0)
def __str__(self):
return self.title
This is my 'Lesson' model
class Lesson(models.Model):
title = models.CharField(max_length=100)
file = models.FileField(upload_to="lesson/pdf")
date_posted = models.DateTimeField(default=timezone.now)
post = models.ForeignKey(Post, on_delete=models.CASCADE)
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse('lesson_upload', kwargs={'pk': self.pk})
This is my Class-based listview that is supposed to display the uploaded lessons based on the posts:
class LessonListView(ListView):
model = Lesson
template_name = 'store/uploaded_lesson.html'
context_object_name = 'lesson'
def get_queryset(self):
self.post = get_object_or_404(post, name=self.kwargs['post'])
return Lesson.objects.filter(post=self.post)
{% extends "store/base.html" %}
{% block content %}
<div id="main">
<table class="table mb-0">
<thead>
<tr>
<th>Title</th>
<th>Author</th>
<th>Download</th>
<th>Delete</th>
</tr>
</thead>
<tbody>
{% for lesson in lesson %}
<tr>
<td>
{% if lesson.file %}
<img src="{{ lesson.file.url }}" style="width:100px;">
{% else %}
{% endif %}
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% endblock %}

You will need another model for the material they are uploading. Something like:
class UploadedPostMaterial(models.Model):
content= models.TextField()
date_uploaded = models.DateTimeField(default=timezone.now)
post = models.ForeignKey(Post, on_delete=models.CASCADE)
user = models.ForeignKey(User, on_delete=models.CASCADE)
This model will contain the uploaded data and tie it to a post. Now when you display all or specific Posts in your app, you can select the related content for each post and display the uploaded content.

Related

how to access 2 models attributes through foreignkey in django

Django learner here, I am trying to build a simple blog website in which i have created two models:
one is Post:
class Post(models.Model):
title = models.CharField(max_length=255)
author= models.ForeignKey(User, null=True, blank=True , on_delete=models.CASCADE)
article = models.TextField()
created_on = models.DateTimeField(auto_now_add=True)
slug = AutoSlugField(populate_from='title', unique=True, null=True, default=None)
category = models.ForeignKey(Category, null=True, blank=True, on_delete=models.CASCADE )
def __str__(self):
return self.title
second is category:
class Category(models.Model):
categories = models.CharField(max_length=24, blank=True)
def __str__(self):
return self.categories
all i am trying to do is to show Category on home page, and when someone click on any category it will open up all the post related to that category.
This is home.html :
{% extends 'blog_pages/base.html' %}
{% block content %}
<div class = "container p-3">
<h3> This is your home page</h3>
</div>
<div class = "container p-1">
<table class="table table-hover table-bordered">
<thead>
<tr>
<th scope="col">Categories</th>
<th scope="col">About</th>
</tr>
</thead>
<tbody>
{% for c in cat %}
<tr>
<th scope="row"><a href="{% url 'all_articles' c %}" ><p> {{c}}</P></a></th>
<td> How you can win in life</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
this is views.py :
def home(request):
cat = Category.objects.all()
return render(request, 'blog_pages/home.html',{'cat': cat})
def all_articles(request, c):
post = Post.objects.filter(category__contains = c).values()
return render(request,"blog_pages/all_articles.html",{'post':post})
I am getting this error " FieldError(
django.core.exceptions.FieldError: Related Field got invalid lookup: contains"
i have tried many possible ways to solve this problem, but nothing works.

How to create a dynamic filter based on the primary key of ForeignKey in ListView?

I am relatively new to Django but the main problem I am facing right now is to create a ListView that will display uploaded documents based on the primary key of my ForeignKey.
I have tried several methods of trying to create the filter and read the online documentation on class-based view but it does not seem to have relevant information on how to use the primary key of my ForeignKey in my filter.
These are my models:
class Post(models.Model):
title = models.CharField(max_length=100)
image = models.ImageField(default = 'default0.jpg',
upload_to='course_image/')
description = models.TextField()
price = models.DecimalField(decimal_places=2, max_digits=6)
date_posted = models.DateTimeField(default=timezone.now)
author = models.ForeignKey(User, on_delete=models.CASCADE)
rating = models.IntegerField(default = 0)
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse('post-detail', kwargs={'pk' : self.pk})
class Lesson(models.Model):
title = models.CharField(max_length=100)
file = models.FileField(upload_to="lesson/pdf")
date_posted = models.DateTimeField(default=timezone.now)
post = models.ForeignKey(Post, on_delete=models.CASCADE)
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse('lesson_upload', kwargs={'pk': self.pk})
Here is my ListView with the filter that is not working:
class LessonListView(ListView):
model = Lesson
template_name = 'store/uploaded_lesson.html'
context_object_name = 'lesson'
# def get_queryset(self):
# return Lesson.objects.filter(Post__pk=self.Post.pk)
def get_queryset(self):
self.post__pk = get_object_or_404(post__pk,
name=self.kwargs['post__pk'])
return Lesson.objects.filter(post__pk=self.post__pk)
Here is my urls.py:
path('post/<int:pk>/lesson_uploaded/', LessonListView.as_view(), name='lesson_uploaded'),
Here is my html:
{% extends "store/base.html" %}
{% block content %}
<div id="main">
<table class="table mb-0">
<thead>
<tr>
<th>Title</th>
<th>Author</th>
<th>Download</th>
<th>Delete</th>
</tr>
</thead>
<tbody>
{% for lesson in lesson %}
<tr>
<td>
{% if lesson.file %}
<img src="{{ lesson.file.url }}" style="width:100px;">
{% else %}
{% endif %}
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% endblock %}
You can try like this:
In urls, add post_id :
path('lessons/<int:post_id>/', LessonListView.as_view()),
Then update the View to get the post_id in get_queryset method:
class LessonListView(ListView):
model = Lesson
template_name = 'store/uploaded_lesson.html'
context_object_name = 'lesson'
def get_queryset(self):
return Lesson.objects.filter(post_id=self.kwargs.get('post_id'))
Also, please don't name list and item of that list in a for loop same, so update it to:
{% for l in lesson %}. // or anything other than lesson
<tr>
<td>
{% if l.file %}

Displaying all of the fields of ManytoMany objects in Django Model Form

I am doing a simple invoice app and i encountered a problem with my django model form. Form is showing all of the ManytoManyfields objects but i would like to display all of their fields not just an objectname.
My models.py:
from django.db import models
import datetime
from django.urls import reverse
# Create your models here.
class Product(models.Model):
item_name = models.CharField(max_length=100)
chinese_name = models.CharField(max_length=100)
erp_number = models.CharField(max_length=20)
unit = models.CharField(max_length=8)
photo = models.ImageField(blank=True, null=True)
price_usd = models.DecimalField(max_digits=8, decimal_places=2)
price_eur = models.DecimalField(max_digits=8, decimal_places=2)
def __str__(self):
return self.item_name
class Batch(models.Model):
batch_name = models.CharField(max_length=100)
product = models.ForeignKey(Product, on_delete=models.CASCADE)
quantity = models.DecimalField(max_digits=5, decimal_places=0)
def __str__(self):
return self.batch_name
class Invoice(models.Model):
invoice_no = models.CharField(max_length=30, default="Proforma Invoice 2018102300001")
products = models.ManyToManyField(Product)
total = models.DecimalField(max_digits=8, decimal_places=2, blank=True, null=True)
date = models.DateField(auto_now_add=False,auto_now=False, default=datetime.datetime.now())
def __str__(self):
return self.invoice_no
def get_absolute_url(self):
return reverse('invoice_detail',kwargs = {'pk':self.pk})
My forms.py:
from django import forms
from django.forms import modelformset_factory, inlineformset_factory
from .models import Invoice, Product
from django.forms.widgets import CheckboxSelectMultiple
class InvoiceForm(forms.ModelForm):
invoice_no =forms.CharField(widget=forms.TextInput(attrs={'size':40}),initial='Proforma Invoice 2018102300001')
date = forms.DateField(widget = forms.SelectDateWidget)
class Meta:
model = Invoice
fields = '__all__'
def __init__(self, *args, **kwargs):
super(InvoiceForm, self).__init__(*args, **kwargs)
self.fields["products"].widget = CheckboxSelectMultiple()
self.fields["products"].queryset = Product.objects.all()
My template:
{% extends 'base.html' %}
{% block content %}
<!DOCTYPE html>
<html lang="en">
<body>
<form method="POST" action="">
{% csrf_token %}
<div clas="row">
<p style="width:20px">{{ form.invoice_no }}</p>
<p>{{ form.date }}</p>
</div>
<div class ="row">
<div class="col-md-12">
<div class="table-responsive">
<table class="table">
<thead>
<tr>
<th scope="col" >Photo</th>
<th scope="col">Name</th>
<th scope="col">ERP number</th>
<th scope="col">Unit</th>
<th scope="col">Price (USD)</th>
<th scope="col">Price (EUR)</th>
</tr>
</thead>
<tbody>
{% for product in form.products.all %}
<tr>
<th scope="row"></th>
<td>{{product.item_name}}</td>
<td>{{form.products.erp_number}}</td>
<td>product.unit</td>
<td>product.price_usd</td>
<td>product.price_eur</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
</div>
<input type="submit" value="Submit">
</form>
</body>
</html>
{% endblock %}
As you can see i am trying to access the fields of Product model by using {% for product in form.products.all %} by it is not working. I've been looking for solution on stackoverflow but haven't found the right answer. Is the a way to display not just an objectname and still keep the self.fields["products"].widget = CheckboxSelectMultiple() widget ?

How to get image connected by Foreign Key via Template in django

i want to get the images form the image model in the template.
class Products(models.Model):
category = models.ForeignKey(Category)
name= models.CharField(max_length=120, unique=True)
slug = models.SlugField(unique = True)
price = models.IntegerField(default=100)
class Image(models.Model):
property = models.ForeignKey(Products, related_name='images')
image = models.ImageField(upload_to='static/images/home',blank=True,null=True)
views.py
def index(request):
queryset = Products.objects.all()
return render_to_response('site/index.html',
locals(),
context_instance=RequestContext(request))
{% for query in queryset %}
<img src='/ {{ query.????? }} ' alt="" width = 'auto' height='340'/>
{% endfor %}
i want to get the images which is connected to that product
i have readed that link
i have tried:
{% for query in queryset %}
<img src='/ {{ query.images_all.0.image }} ' alt="" width = 'auto' height='340'/>
{% endfor %}
but no success ..
just try to understand the model that how i get the image url from models which related with foreignkey relationship.
my models:
class Product(models.Model):
title = models.CharField(max_length = 400)
slug = models.SlugField(max_length = 400,unique=True,null=True,blank=True)
is_popular = models.BooleanField(default=True)
category = models.ForeignKey(Category,on_delete=models.CASCADE)
subcategory = models.ForeignKey(Subcategory,on_delete=models.CASCADE,null=True,blank=True)
childcategory = models.ForeignKey(Childcategory,on_delete=models.CASCADE,null=True,blank=True)
brand = models.ForeignKey(Brand,on_delete=models.CASCADE,null=True,blank=True)
description = models.TextField()
is_active = models.IntegerField(choices=STATUS_CHOICES)
created_date = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.title
def save(self, *args, **kwargs):
self.slug = unique_slug_generator(self)
super(Product, self).save(*args, **kwargs)
def show_image(self):
return self.productmeaserment_set.first().first_image()
class ProductMeaserment(models.Model):
product = models.ForeignKey(Product,on_delete=models.CASCADE)
measerment = models.ForeignKey(Measerment,on_delete=models.CASCADE,null=True,blank=True)
selling_price = models.DecimalField(max_digits=20,decimal_places=2)
offer_price = models.DecimalField(max_digits=20,decimal_places=2)
available_quantity = models.IntegerField();
is_active = models.IntegerField(choices=STATUS_CHOICES)
created_date = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.measerment.name
def first_image(self):
return self.productmeasermentimage_set.first()
class ProductMeasermentImage(models.Model):
productmeaserment = models.ForeignKey(ProductMeaserment,on_delete=models.CASCADE)
image = models.FileField(upload_to='uploads/products')
is_active = models.IntegerField(choices=STATUS_CHOICES)
created_date = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.productmeaserment.product.title
views.py
from products.models import Product
def adminpanel(request):
products=Product.objects.all()
return render(request,'adminpanel/index.html',{'productsall':products})
templates/adminpanel/index.html
{% for item in productsall %}
<tr>
<div class="border1">
<td class="image-cell">
<img src="{{item.show_image.image.url}}"> #this is how i got image url.
</td>
</div>
<td data-label="title">{{item.title}}</td>
<td data-label="category">{{item.category}}</td>
<td data-label="subcategory">{{item.subcategory}}</td>
<td data-label="brand">
{{item.brand}}
</td>
<td data-label="description">
{{item.description}}
</td>
<td class="created">
{{item.created_date}}
</td>
</tr>
<tr>
{% endfor %}
There is so much wrong with your code, I suggest that you do the Django Tutorial first.
https://docs.djangoproject.com/en/1.8/intro/tutorial01/
But if you wan't it working, here is how:
models.py
class Product(models.Model):
category = models.ForeignKey(Category)
name= models.CharField(max_length=120, unique=True)
slug = models.SlugField(unique = True)
price = models.IntegerField(default=100)
def first_image(self):
# code to determine which image to show. The First in this case.
return self.images[0]
class ProductImage(models.Model):
image = models.ImageField(upload_to='static/images/home',blank=True,null=True)
product = models.ForeignKey(Product, related_name='images')
views.py
def index(request):
queryset = Products.objects.all()
return render_to_response('site/index.html', {'products': queryset})
index.html
{% for product in products %}
<img src="{{ product.first_image.src }}" alt="" width="auto" height="340"/>
{% endfor %}

Using ListView in django, getting __init__() takes exactly 1 argument (2 given)

I am very new to django, I am trying to display the list of albums i have in my database. This is the Album model
class Album(models.Model):
"""Album model"""
title = models.CharField(max_length=255)
prefix = models.CharField(max_length=20, blank=True)
subtitle = models.CharField(blank=True, max_length=255)
slug = models.SlugField()
band = models.ForeignKey(Band, blank=True)
label = models.ForeignKey(Label, blank=True)
asin = models.CharField(max_length=14, blank=True)
release_date = models.DateField(blank=True, null=True)
cover = models.FileField(upload_to='albums', blank=True)
review = models.TextField(blank=True)
genre = models.ManyToManyField(Genre, blank=True)
is_ep = models.BooleanField(default=False)
is_compilation = models.BooleanField(default=False)
class Meta:
db_table = 'music_albums'
ordering = ('title',)
def __unicode__(self):
return '%s' % self.full_title
My view is
class album_list(ListView):
template_name = "/music/album_list.html"
context_object_name = 'list_of_albums'
#paginate_by = '15'
def get_queryset(self):
return Album.objects.all()
I am able to add albums from the admin interface, but on going to the /albums/ url to display them, I get init() takes exactly 1 argument (2 given) error.
The template I am using
{% extends "music/base_music.html" %}
{% block title %}Music Albums{% endblock %}
{% block body_class %}{{ block.super }} music_albums{% endblock %}
{% block content_title %}
<h2>Music Albums</h2>
{% include "music/_nav.html" %}
{% endblock %}
{% block content %}
<table>
<tr>
<th>Band</th>
<th>Album</th>
</tr>
{% for album in list_of_albums %}
<tr class="{% cycle 'odd' 'even' %}">
<td class="band">{{ album.band }} </td>
<td class="album">{{ album.full_title }}</td>
</tr>
{% endfor %}
</table>
{% endblock %}
I have gone through the answers to similar questions already asked here, but couldn't get the code to work.
Usually this is because you forgot to put .as_view() in your urls.py:
Instead of
(r"", 'SomeName.views.album_list'),
put
(r"", SomeName.views.album_list.as_view()),
Remember to change SomeName :)