Objects have the same ID on production in Django App - python

I have project in Python Django. It has three models: Project, Files and Agreement.
class Project(models.Model):
project_name = models.CharField(max_length=50)
client_name = models.CharField(max_length=50)
agreement_number = models.CharField(max_length=20)
brief_status = models.CharField(max_length=20, choices=BRIEF_CHOICES, default='nieuzupelniony')
agreement_status = models.CharField(max_length=20, choices=AGREEMENT_CHOICES, default='niedostarczona')
resources_status = models.CharField(max_length=20, choices=RESOURCES_CHOICES, default='niedostarczone')
payment_status = models.CharField(max_length=20, choices=PAYMENT_CHOICES, default='nieoplacone')
message = models.CharField(max_length=200, default='Brak wiadomoĊ›ci')
project_date = models.CharField(max_length=10)
status = models.CharField(max_length=100)
user = models.ForeignKey(User, on_delete=models.CASCADE, related_name="project")
modifications = models.CharField(max_length=15, default='2')
corrections = models.CharField(max_length=15, default='3')
def __str__(self):
return self.project_name
class Files(models.Model):
name = models.CharField(max_length=50)
upload = models.FileField(upload_to='uploads/', validators=[validate_file_extension])
user = models.ForeignKey(User, on_delete=models.CASCADE, related_name="files")
project = models.ForeignKey(Project, on_delete=models.CASCADE)
def __str__(self):
return self.name
class Agreement(models.Model):
name = models.CharField(max_length=50)
upload = models.FileField(upload_to='uploads/', validators=[validate_file_extension])
user = models.ForeignKey(User, on_delete=models.CASCADE, related_name="agreement")
project = models.ForeignKey(Project, on_delete=models.CASCADE)
def __str__(self):
return self.name
In app we have an admin and users. Every user has welcome.html page which display every user project, every user agreement and objects from one additional model which isn't important. When user click on project (user goes to project_detail.html), he can see information about project and there are all files from this project.
def panel(request):
if request.user.is_authenticated:
queryset = Project.objects.filter(user=request.user)
queryset2 = Invoice.objects.filter(user=request.user)
queryset3 = Files.objects.filter(user=request.user)
queryset4 = Agreement.objects.filter(user=request.user)
return render(request, 'projects/welcome.html', {'project': queryset, 'invoice': queryset2, 'files': queryset3, 'agreement': queryset4})
else:
return render(request, 'projects/welcome.html')
Admin has user_detail.html page, and there are all files and projects and agreements for this user.
class UserDetailView(DetailView):
model = User
template_name = 'projects/user_detail.html'
context_object_name = 'user'
def get_context_data(self, **kwargs):
context_data = super().get_context_data(**kwargs)
context_data['invoice'] = Invoice.objects.all()
context_data['project'] = Project.objects.all()
context_data['files'] = Files.objects.all()
context_data['agreement'] = Agreement.objects.all()
return context_data
Here is a part of my template.
<div class="block bg-white rounded shadow-2xl text-indigo-800 m-2 p-4 w-full h-full">
<p class="text-3xl text-left mb-2 pb-2 border-b">Pliki</p>
{% for files in files.all %}
{% if files.user == user %}
<div class="flex justify-between mb-2 pb-2 border-b pr-32">
{{files.name}}
<p class="text-xl font-thin text-indigo-800 hover:text-indigo-600 text-left mb-2">{{files.project}}</p>
</div>
{% endif %}
{% endfor %}
</div>
Unfortunetly when I tried (as admin) edit any of file I've got an error:
Exception Type: MultipleObjectsReturned
Exception Value:
get() returned more than one Files -- it returned 8!
So to each project you can assign file and agreement. I have problem with my database. On my local environment everything is fine. On local SQlite3 every file object has unique ID, unfortunetly on my producton, on phpMyAdmin every object has the same ID = 0. Where I can find error? I tried working with my models and database, unfortunetly I can't find what is going on. So now I cannot update file for my user even by my Django Admin Dashboard, because I've got an error.

Hi you have a problem in your template you use files in files.all so when you do files.project you get more than one
{% for files in files.all %}
you need to do :
{% for file in files.all %}
....
{{file.project}}</p>

Related

Getting profile picture of blogposter in Django

When I display a blog post in HTML using a for loop
{% for post in posts %}
<div class="blogpost">
<h3><strong>{{post.title}}</strong></h3>
<img class="thumbnail" src="{{author.imageURL}}">
<h7>{{post.date}} - {{post.author}}</h7>
<br>
<hr>
<br>
{{post.context|linebreaks}}<br><br>
</div>
<br>
{% endfor %}
it works perfectly fine, except the authors profile picture does NOT get displayed.
I get the posts by getting all posts in my views.py from my models.py. The thing is that the profile picture of the user posting the blog isn't stored in the "post" model in the database. It is stored in the "Customers". Everybody should be able to read and post blogs. The admin (me) can later delete unwanted posts.
I have tried making a for loop using an array key:value in JavaScript. That is not very secure, because everybody just gets all users and all profilepictures through the whole database. That might not be a good idea.
This is my models.py
class Customer(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE, null=True, blank = True)
name = models.CharField(max_length=200, null=True)
email = models.EmailField(max_length=200, null=True)
about = models.CharField(max_length=100, null=True)
image = models.ImageField(null=True, blank=True)
#property
def imageURL(self):
try:
url = self.image.url
except:
url = 'placeholder.png'
return url
def __str__(self):
return self.name
class Post(models.Model):
title = models.CharField(max_length=200, null=True)
context = models.TextField(max_length=250, blank=True,
validators=[MaxLengthValidator(250)])
author = models.CharField(max_length=200, null=True)
from datetime import date
date = models.DateField(("Date"), default=date.today)
views.py
def homepage(request):
if request.user.is_authenticated: # Everybody has to be logged in
posts = Post.objects.all()
authors = Customer.objects.filter()
context = {'posts':posts, 'authors':authors}
return render(request, 'store/homepage.html', context)
That means that I want the user to see the persons profile picture in the corner of the blog post.
First I think you need to link the author in the Post model to a Customer with a foreignkey:
Then you can acces author fields like
{{ post.author.xyz }}
Currently your context contains authors as a queryset:
authors = Customer.objects.filter()
context = {'posts':posts, 'authors':authors}
But in your template you use it as if it were a single Customer:
<img class="thumbnail" src="{{author.imageURL}}">
And be aware of the typo "author" and "authors"
It is unclear what you meant by {{author.imageURL}} as author is QuerySet( that results in collection of authors).
You probably meant the related author to post which would be post.author
Other than that you should pass image URL to template and not ImageField string representation as documented
So it should be something in a line of
{{ post.author.imageURL.url }}

Check User Perms Django

I am trying to use Django's default permissions to only show the link to the blog post page if they have the blog post permissions.
The wonderful Django documentation provides the following:
Assuming you have an application with an app_label foo and a model named Bar,
to test for basic permissions you should use:
add: user.has_perm('foo.add_bar')
change: user.has_perm('foo.change_bar')
delete: user.has_perm('foo.delete_bar')
view: user.has_perm('foo.view_bar')
My app is named about
Here is my model:
# models.py
class BlogPost(models.Model):
title = models.CharField(max_length=120)
description = models.TextField(max_length=250, null=True)
image = models.ImageField(upload_to='blog/main')
content = HTMLField()
date_posted = models.DateTimeField(default=timezone.now)
author = models.ForeignKey(User, on_delete=models.CASCADE)
draft = models.BooleanField(default=False)
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse("post-detail", kwargs={"pk": self.id})
Here is my HTML where I am trying to filter
# base.html
{% if user.has_perm('about.add_blogPost') %}
<li {% if url_name == 'post' %}class="nav-item active"{% else %}class="nav-item"{% endif %}>Add Post</li>
{% endif %}
Whenever I follow it just as the documentation has written, I get:
Could not parse the remainder: '('about.add_blogPost')' from 'user.has_perm('about.add_blogPost')'
What am I doing wrong?
try
{% if user.has_perm 'about.add_blogPost' %}

Django: path doesn't find the right primary key in url path

I'm using django2 and I get an error when I access this url:
http://127.0.0.1:8000/hotes/12/access/7/update
I get an error 404 "None access object was found"
To make a long story short:
I want to update an object linked to another. To do so, I have to send through the link, both primary keys (12 and 7 in the url). Also, I use the generic view "UpdateView" given by Django.
This is the path concerned in my project.urls:
urlpatterns = [
path('hotes/<int:pk>/access/<int:access_pk>/update/',views.AccessUpdateView.as_view(), name='access_update'),
path('hotes/add',views.host_add, name='host_add'),
path('hotes/<int:pk>/', include([
path('edit',views.HostUpdateView.as_view(), name='host_update'),
path('delete',views.host_delete, name='host_delete'),
])),
path('hotes/<int:pk>/add/', include([
path('access',views.access_add, name='access_add'),
path('oncall',views.onCall_add, name='onCall_add'),
path('network',views.network_add, name='network_add'),
])),
path('hotes/<int:pk>/',views.host_view, name='host_view'),
path('hotes/',views.hosts_view, name='hosts_view'),
path('', views.home, name='home'),
path('admin/', admin.site.urls),
]
I want the second primary key to be used in my view "AccessUpdateView".
This is a part of my models.py:
class Host(models.Model):
name = models.CharField(max_length=30, unique=True)
usage = models.CharField(max_length=30, blank=True)
function = models.CharField(max_length=30, blank=True)
production = models.NullBooleanField(blank=True, null=True)
place = models.CharField(max_length=30, blank=True)
type = models.CharField(max_length=30, blank=True)
processor = models.DecimalField(max_digits=3, decimal_places=2, null=True, blank=True)
storage = models.CharField(max_length=10, blank=True)
memory = models.CharField(max_length=10, blank=True)
dns_inner = models.CharField(max_length=50, blank=True)
dns_extern = models.CharField(max_length=50, blank=True)
os = models.ForeignKey(Os, null=True, related_name='hosts', on_delete=models.SET_NULL, blank=True)
class Access(models.Model):
service = models.CharField(max_length=20)
client_access = models.NullBooleanField(blank=True, null=True)
ip = models.GenericIPAddressField()
login = models.CharField(max_length=30, blank=True)
password = models.CharField(max_length=50, blank=True)
host = models.ForeignKey(Host, related_name='access', on_delete=models.CASCADE)
As you can see on host can have multiple access but an access in linked to only one host.
This is the view concerned:
class AccessUpdateView(UpdateView):
model = Access
fields = ('service','client_access','ip','login','password', )
template_name = 'access_update.html'
pk_url_kwarg = 'access_pk'
context_object_name = 'access'
def form_valid(self, form):
access = form.save(commit=False)
host_id = self.kwargs['pk']
access.host_id = host_id
access.save()
return redirect('host_view', pk=host_id)
EDIT: new error when I try to access the url:
NoReverseMatch at /hotes/12/access/7/update/
Reverse for 'host_view' with arguments '('',)' not found. 1 pattern(s) tried: ['hotes\/(?P[0-9]+)\/$']
EDIT:
The error was coming from "access_update.html"
I removed the href in the Hote link which contained {% url host.pk %}
{% extends 'base.html' %}
{% load widget_tweaks %}
{% block title %}Modifier Acces{% endblock %}
{% block breadcrumb %}
<li class="breadcrumb-item">Hotes</li>
<li class="breadcrumb-item">Hote</li>
<li class="breadcrumb-item active">Modification Acces</li>
{% endblock %}
{% block contenu %}
<form method="post" novalidate>
{% csrf_token %}
{% include 'includes/form.html' %}
<button type="submit" class="btn btn-success">Modifier</button>
</form>
{% endblock %}
The question is what is the right way to write the pk of the host in the url?
(host_id doesn't work)
If you want to use access_pk, then you should set pk_url_kwarg = 'access_pk' in the view.
In your form_valid method, you are using host without defining it. If pk from the URL is the host id, then you can access it with self.kwargs['pk'].
def form_valid(self, form):
access = form.save(commit=False)
host_id = self.kwargs['pk']
access.host_id = host_id
access.save()
return redirect('host_view', pk=host_id)
Inside the template for the AccessUpdateView, you have access to access since that is the object that is being updated. If you want to use the host or its id, you should access it via access.
{% url 'host_view' access.host_id %}

Django 1.8.3: Showing many-to-many additional fields in template

I have the following problem: A project can have multiple Roles, How do I show the roles field in a template? project.role shows blank and the problem is even after using _set.all in the template, I still do not get the contents from the database to show.
Model.py
class Project(models.Model):
"""
Information for each Project
"""
project_name = models.CharField(max_length=255, blank=True, null=True, unique=True)
project_description = models.TextField(null=True, blank=True)
project_url = models.URLField(max_length=200, null=True, blank=True)
#For Admin Purposes and filtering, to keep track of new and old in the database by administrative users
date_added = models.DateTimeField(auto_now_add=True, null=True, blank=True, verbose_name=_('Date added'))
last_modified = models.DateTimeField(auto_now=True, null=True, blank=True, verbose_name=_('Last modified'))
class Role(models.Model):
"""
Information for Role
"""
role = models.CharField(max_length=255, blank=True, null=True)
project_role = models.ManyToManyField(Project)
View.py
class ProjectView(ListView):
template_name = '_projects.html'
model = Project
def get_context_data(self, **kwargs):
context = super(ProjectView, self).get_context_data(**kwargs)
context['projects'] = Project.objects.all()
return context
Template
{% for project_info in projects %}
{{project_info.project_name}}
</br>
{{project_info.project_description}}
</br>
{{project_info.project_url}}
</br>
{% for rolling in project_info.project_role_set.all %}
{{rolling}}
{% endfor %}
{% endfor %}
Try this:
{% for rolling in project_info.role_set.all %}
{{rolling}}
{% endfor %}

Display data from models in website

I am new to Django. I want to display latest data entered from models to the website.
models.py
class Service(models.Model):
service_name = models.CharField(max_length=200)
service_code = models.IntegerField(default=0, unique=True)
views.py
def Latest(return):
latest_services = Service.objects.order_by('service_name')
index.html
{{ service_name }}
Latest Services Goes here
When I run the code nothing is displayed!
You need to iterate over the queryset:
<ul>
{% for service in latest_services %}
<li>{{ service.service_name }}</li>
{% endfor %}
</ul>
Anyway, if you want to display the latest entries, you should add a new field to your model with the date. For example:
class Service(models.Model):
created_on = models.DateTimeField(auto_now=True)
service_name = models.CharField(max_length=200)
service_code = models.IntegerField(default=0, unique=True)
And then in your query:
latest_services = Service.objects.order_by('created_on')

Categories