Hi I have ready Django project and I want to create a control panel for it, for example I want to add a field with the name of the site, a field with a description of the site, and a field with the logo of the site, and I call them in the templates instead of changing them manually through the editor every time.
I upload the website logo to the static file and want to add an option to change it from the control panel instead of manually replacing it from the server.
I have attached an illustration of what I want to reach.
Thank you
I searched and did not find a solution for this, but I want to share the solution that I adopted myself
I created a new application called Settings and through it I created a modle for each setting I wanted.
UPDATED
I create new model:
from django.db import models
from django.utils.translation import gettext_lazy as _
class Option(models.Model):
key = models.CharField(max_length=50, verbose_name=_('Key'), null=True, blank=True, unique=True)
value = models.CharField(max_length=50, verbose_name=_('Value'), null=True, blank=True)
def __str__(self):
return self.key
Thus, you can use the values stored in the database:
#register.simple_tag
def get_option(key, default):
op = Option.objects.filter(key=key).first()
if op and op.value != '':
option = op.value
else:
option = default
return option
Related
I created an app with django and python3 containing several tutorials, which in turn contain multiple content entrys that are saved in another table. Each tutorial is represented by an entry in the exercises tutorial model. I want to be able to sort the tutorials and the contents in the django admin panel. It works fine for the inline tutorial contents with SortableInlineAdminMixin class. It also works fine if I create new tutorials from scratch without having any objects saved before (it works local on my pc if I clone this project and set it up from scratch)
My problem now is, that I have the app setup like you see in the code and pictures below on a ubuntu server with apache, but I can't sort the tutorials (the inline contents still work fine). If i drag and drop them to a new position and reload, they don't save at their new position and fall back to their old position.
Tutorial and TutorialContent model:
from django.db import models
from ckeditor_uploader.fields import RichTextUploadingField
# Page for tutorials
class Tutorial(models.Model):
title = models.CharField(max_length=60)
order = models.PositiveIntegerField(default=0, null=False, unique=True)
# Timestamp
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
class Meta:
ordering = ['order']
def __str__(self):
return self.title
# Content for tutorials
class TutorialContent(models.Model):
lesson_page = models.ForeignKey(Tutorial, related_name='tutorial_content', on_delete=models.CASCADE)
content = RichTextUploadingField()
order = models.PositiveIntegerField(default=0, null=False)
# Timestamp
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
class Meta:
ordering = ['order']
def __str__(self):
description = 'Order - ' + str(self.order)
return description
Tutorial and TutorialContent admin:
from django.contrib import admin
from .models import Tutorial, TutorialContent
from adminsortable2.admin import SortableInlineAdminMixin, SortableAdminMixin
class TutorialContentInline(SortableInlineAdminMixin, admin.TabularInline):
model = TutorialContent
class TutorialAdmin(SortableAdminMixin, admin.ModelAdmin):
model = Tutorial
inlines = [TutorialContentInline]
list_display = ['title']
admin.site.register(Tutorial, TutorialAdmin)
Django admin tutorial model panel:
SQLite3 view of the corresponding table:
Maybe a little to late, but:
If there is already some model instance persisted in your db when you add the adminsortable2 field in your model, the ordering will not works, you need to build the order a first time with:
python manage.py reorder your_app.YourModel
Source: https://django-admin-sortable2.readthedocs.io/en/latest/usage.html#initial-data
Hoping this can help.
I have a few apps within my Django project. There are two apps that I am currently working with "Application" and "User" and I have two questions related to models:
Question 1:
I want to design it in such a way so that external users submit their contact form on Application/templates/Application/Apply.html and the info would get added to the database. Internal users would be able to add external users as well but from a different template: User/templates/User/AddNewContact.html
I am able to add a new contact from an internal user's perspective:
User/models.py
class Contact(models.Model):
ContactName = models.CharField(max_length = 250, default='')
ContactResidence = models.CharField(max_length = 250, default='')
Tel = models.CharField(max_length = 250, default='')
def get_absolute_url(self):
return reverse('User:ContactDetails', kwargs={'pk': self.pk}
)
def __str__(self):
return self.ContactName
class Locations(models.Model):
contact = models.ForeignKey(Contact, on_delete=models.CASCADE)
Country = models.CharField(max_length=250, default='')
def __str__(self):
return self.Country
I was going to just copy this model and paste it into Application/models.py but there are two problems:
1) I don't want external users to be directed to URL: User:ContactDetails and technically, it is not going to work out because I will build the authentication later on.
2) I feel that by copying and pasting I am breaking the 'don't repeat yourself" rule.
Should I connect two models using the foreign keys? What are the best practices in this case?
Question 2
Am I working with one-to-many relationship according to the model provided? I want to have one contact with his personal info (tel/email/address) and a number of branch locations across the world associated with that contact.
To be used a relationship one to many, you can be doing as after:
On models of father app (father table):
class Department(models.Model):
dept_id = models.AutoField(primary_key=True)
On models of child app (child table):
from appname.models import Department
class Office(models.Model):
office_id = models.AutoField(primary_key=True)
name = models.CharField(max_length=200)
dept = models.ForeignKey(Department, on_delete=models.CASCADE)
It helped me.
Question 1: Well, you don't need to copy paste the model. You can use models from other django apps anytime, just need to import it. Basically what you should do is, instead of linking the url directly to the template in the Applications app, you should connect it to a view. In the view file you can import the models from User.models import *, and use them normally.
Question 2: As far as I understand the question your structure provides what you want: one contact (with personal info) associated with several countries. Except that you should replace Agent by Contact in contact = models.ForeignKey(Agent, on_delete=models.CASCADE)
Question 1: Note that the 'get_absolute_url' method is only called if you don't provide a success url in your view. If you are using a CreateView or FormView you can specify the success url by overriding the get_success_url method, for example:
class ContactCreateView(CreateView):
model = Contact
fields = ['ContactName', 'ContactResidence', 'Tel']
def get_success_url(self):
if not self.request.user.internal: # e.g. internal is a User bool field
return HttpResponseRedirect('some/external/url/')
return super().get_success_url() # call get_absolute_url model method.
The DRY principle is respected.
Question 2: Yes, the question you need to ask yourself is 'does a model instance (In this case Contact) have many instances of another model (Location)?' If the answer is yes, then the M2M field should go into your Contact model. See the django docs explaining the pizza/toppings example.
The apps should be in the same project and you can import one model as:
import appName.models or
from appName.models import ClassName
In app2 models you can use foreignKey or manyTomany after importing the class:
from appsName.models import ClassName
class Person(models.Model):
con = ForeignKey(ClassName)
I've got a two part question regarding Django Admin.
Firstly, I've got a Django model Classified that has a foreign key field from another table Address. On setting data, I've got no issues with any of the fields and all fields get saved correctly.
However, if I want to edit the foreign field in the entry in Classified, it doesn't display the old/existing data in the fields. Instead it shows empty fields in the popup that opens.
How do I get the fields to display the existing data on clicking the + so that I can edit the correct information?
Secondly, I'm sure I've seen search fields in Django Admin. Am I mistaken? Is there a way for me to implement search in the admin panel? I have over 2 million records which need to be updated deleted from time to time. It's very cumbersome to manually go through all the pages in the admin and delete or edit those.
Adding Model Code:
Classified
class Classified(models.Model):
id = models.AutoField(primary_key=True)
name = models.CharField(max_length=256)
contact_person = models.CharField(max_length=300, blank=True)
email = models.CharField(max_length=100, blank=True)
address = models.ForeignKey(Address)
subcategory = models.ForeignKey(Subcategory)
Address
class Address(models.Model):
id = models.AutoField(primary_key=True)
build_add = models.CharField(max_length=255)
street_add = models.CharField(max_length=255)
area = models.CharField(max_length=255)
city = models.ForeignKey(Cities)
The + means just that - add a new instance of the related object and relate the object you're editing to that. Because you're adding a new object it will be blank to start. If you want to be able to edit existing related objects from another object's admin you need to use inlines.
In your app's admin.py have something like:
from django.contrib import admin
from yourapp.models import Address, Classified
class AddressInline(admin.TabularInline):
model = Address
class ClassifiedAdmin(admin.ModelAdmin):
inlines = [AddressInline,]
admin.site.register(Classified, ClassifiedAdmin)
Adding search from there is really easy.
...
class ClassifiedAdmin(admin.ModelAdmin):
inlines = [AddressInline,]
search_fields = [
'field_you_want_to_search',
'another_field',
'address__field_on_relation',
]
...
Note the double underscore in that last one. That means you can search based on values in related objects' fields.
EDIT: This answer is right in that your foreignkey relationship is the wrong way round to do it this way - with the models shown in your question Classified would be the inline and Address the primary model.
i have following models
class tags(models.Model):
tag = models.CharField(max_length=15) # Tag name
tagDescription = models.TextField() # Tag Description
tagSlug = models.TextField() # Extra info can be added to the existing tag using this field
class stores(models.Model):
storeName = models.CharField(max_length=15) # Store Name
storeDescription = models.TextField() # Store Description
storeURL = models.URLField() # Store URL
storePopularityNumber = models.IntegerField(max_length=1) # Store Popularity Number
storeImage = models.ImageField(upload_to=storeImageDir) # Store Image
storeSlug = models.TextField() # This is the text you see in the URL
createdAt = models.DateTimeField() # Time at which store is created
updatedAt = models.DateTimeField() # Time at which store is updated
storeTags = models.ManyToManyField(tags)
class tagsAdmin(admin.ModelAdmin):
list_display = ('tag', 'tagDescription', 'tagSlug')
class storesAdmin(admin.ModelAdmin):
list_display = ('storeName','storeDescription','storeURL',
'storePopularityNumber','storeImage',
'storeSlug','createdAt','createdAt','storeTags'
)
admin.site.register(tags,tagsAdmin)
admin.site.register(stores,storesAdmin)
Whenever I am trying to run command : python manage.py syncdb
I got the error: django.core.exceptions.ImproperlyConfigured: 'storesAdmin.list_display[8]', 'storeTags' is a ManyToManyField which is not supported.
I don't understand what I am doing wrong here. I want to simply display all the models in the django admin site.
You can't reference a Many2ManyField like that, you have to use a method instead in the stores class that looks like this
def get_tags():
return self.storeTags.all()
and reference that in your list_display(...'get_tags')
This is done because the M2M field would result in lots of SQL queries that would slow the entire thing down so therefore the choice would have to come from the developer and not from the framework.
Please check:
ModelAdmin.list_display
"ManyToManyField fields aren’t supported, because that would entail executing a separate SQL statement for each row in the table. If you want to do this nonetheless, give your model a custom method, and add that method’s name to list_display. (See below for more on custom methods in list_display.)"
You can use a custom method to show values of ManyToManyField or simply remove storeTags from list_display
I am working on creating a simple contest submission system using django. This is my first real django project. Basically each user can view a list of problems, submit a file, and view a results page.
Each problem can be associated with multiple contests, and different contests can use the same problem. Because of this, both problem and contest have a manyToManyField with each other. This is what is causing my problem.
Here is the initial models.py implementation I am going with:
startfile
from django.db import models
class User(models.Model):
username = models.CharField(max_length=50)
firstname = models.CharField(max_length=50)
lastname = models.CharField(max_length=50)
class Problem(models.Model):
name = models.CharField(max_length=50)
filename = models.CharField(max_length=300)
contests = models.ManyToManyField(Contest)
class Contest(models.Model):
name = models.CharField(max_length=50)
problems = models.ManyToManyField(Problem)
date = models.DateField()
class Submission(models.Model):
user = models.ForeignKey(User)
problem = models.ForeignKey(Problem)
filename = models.CharField(max_length=300)
endfile
Is there a simple way to fix this? Or should I rethink my entire layout? I tried breaking each class into its own django app but I don't think thats how I should do it. The error I get is that Contest can not be found (because it exists lower in the file).
All advice is appreciated!
You don't need a ManyToManyField in both Contest and Problem. Many-to-many fields are already bidirectional. Just put it on one - doesn't matter which.
Djano will automatically create the reverse relation for you, so you only need to create it one end, eg.
class Problem(models.Model):
name = models.CharField(max_length=50)
filename = models.CharField(max_length=300)
contests = models.ManyToManyField(Contest, related_name='problems')
related_name gives you the possibility to assign a name to the reverse relation. Without defining the relation on the Contest model, you can then access eg. a_contest.problems.all()!