When I am doing the flatpage tutorial, I was getting error for SITE_ID not being set. I inserted SITE_ID=1 in the settings file and everything worked fine. But I don't know what this actually means.
I read through the django docs. but I am not totally clear what its use.
when will I use something like SITE_ID=2.
On the same note, I used the following snippet in my code without actually knowing what it does:
current_site=Site.objects.get_current()
I assume this has something to do with SITE_ID but may be not.
Some example to demonstrate where SITE_ID could take different values than 1 would help.
It is helpful is you use your code on multiple sites, or if you share a database with another site. An example from the documentation:
from django.db import models
from django.contrib.sites.models import Site
from django.contrib.sites.managers import CurrentSiteManager
class Photo(models.Model):
photo = models.FileField(upload_to='/home/photos')
photographer_name = models.CharField(max_length=100)
site = models.ForeignKey(Site)
objects = models.Manager()
on_site = CurrentSiteManager()
With this model, Photo.objects.all() will return all Photo objects in the database, but Photo.on_site.all() will return only the Photo objects associated with the current site, according to the SITE_ID setting.
Put another way, these two statements are equivalent:
Photo.objects.filter(site=settings.SITE_ID)
Photo.on_site.all()
From documentation:
SITE_ID
Default: Not defined
The ID, as an integer, of the current site in the django_site database table. This is used so that application data can hook into specific sites and a single database can manage content for multiple sites.
Related
I was referring this link : Django: Get model from string?
. And, I found there is a way to do this by using apps.get_model. But,In my scenario, the model can be from other apps. So, I can't actually name the app_name here. Is there any way to do this ?
If you don't care which app the model comes from, you can do it the following way:
from django.apps import apps
def get_model_from_any_app(model_name):
for app_config in apps.get_app_configs():
try:
model = app_config.get_model(model_name)
return model
except LookupError:
pass
model = get_model_from_any_app('SomeModelName')
But in Django models in different apps can have the same name, i.e. your project can have model Post in your blog app and model Post in your news app etc.
So this way you can end up with not the model you expect, if they have duplicate names across apps (i.e. you probably should not do it this way, just think why in the world would you want a semi-random model?).
Docs which explain the code:
https://docs.djangoproject.com/en/2.0/ref/applications/#django.apps.apps.get_app_configs
https://docs.djangoproject.com/en/2.0/ref/applications/#django.apps.AppConfig.get_model
Hello everyone how is it going?
I've just started using Django recently, and I've started getting my head around it; I need to build a website about cars, with two major APPS:
CarsCatalogue;
News Section;
I find the fact that I can manage the news from the admin panel extremely useful. I have created the typical model:
class Post(models.Model):
title = models.CharField(max_length = 140)
date = models.DateTimeField()
body = models.TextField()
def __str__(self):
return self.title
With the urls.py as follows
url(r'^(?P<pk>\d+)$', DetailView.as_view(
model = Post,
template_name="news/post.html"))
url(r'^$', ListView.as_view(
queryset=Post.objects.all().order_by("-date")[:25],
template_name="news/news.html")),
This is great! I can manage the News app Extremely easyly from the admin panel. Now I have a page for each news: news/1; news/2 etc etc;
But when i go down to the CarsCatalogue, and I would really need to simplify my life because I have plenty of cars with a personal page each to add, I am instead finding myself needing to modify the urls.py for each car I need to add, and it seems I have to modify the views.py for each car -I am using render- am I right?
I mean, does it make sense to have a Views.py with one hundred different functions calling one hundred pages?
And then if I want to create a list with all the urls of the CarCatalogue, having to write every link one by one?
Is this the way to use Django in this case?
I would create another "news-style" APP for CarsCatalogue, that would be so much more easy for me to manage through the Admin Panel, but I need each url to show the car name, like: CarsCatalogue/Seat-Ibiza and not like CarsCatalogue/1.
Maybe I can do something like the news APP, but changing the way urls are generated and shown?
I am asking you all of this after I read the documentation and several Google topics and other resources;
I hope you guys will be able to clear the fog around my head;
With all the Respect such a community deserves,
Sincerely,
-oKi
EDIT n*1
It's been 3 hours of reading, trying, modifying, erasing, trying again.
I read a lot of stuff, but at the same time I got pheraps even more confused, because I found so many things while looking for how to "slug"ify the urls (that is indeed what I was looking for [now I can indeed use the admin panel to do what I wanted!] thanks) that I ended up mixing a lot of stuff. So, using the NEWS application, what I have done so far:
python3.5 manage.py flush, makemigrations, migrate, createsuperuser
I modified the news/models.py, so that it now looks like this:
from django.db import models
from django.template.defaultfilters import slugify
class Post(models.Model):
title = models.CharField(max_length = 140)
date = models.DateTimeField()
body = models.TextField()
slug = models.SlugField(title, max_length=100, unique=True)
def __str__(self):
return self.title
def slug(self):
return slugify(self.title)
I modified the news/admin.py, so that it now looks like this:
from django.contrib import admin
from news.models import Post
admin.site.register(Post)
class NewsAdmin(admin.ModelAdmin):
prepopulated_fields = {"slug": (Post.slug)} <!-- that seems makes sense looking at the Model - I also tryed {"slug": (title,)}, {"slug": (Post.title)}-->
I modified the news/urls.py, so that it now looks like this:
from django.conf.urls import url
from django.views.generic import ListView, DetailView
from news.models import Post
urlpatterns = [
url(r'^$', ListView.as_view(
queryset=Post.objects.all().order_by("-date")[:25],
template_name="news/news.html")),
url(r'^(?P<slug>[\w-]+)$', DetailView.as_view(
model = Post,
template_name="news/post.html")),
]
then I give:
python3.5 manage.py runserver
and it runs with no problem.
So I go to /admin, I create a new post, it creates it...
But then what happens?
It still uses the old "paradigm" to generate the url, including the old keys(id's) it was using before I erased the client... so... what I expected to be something like mysite/news/new-human-level-urld-news
turns out to be mysite/news/11.
LOL :D and, luckily, the browser gives me also an error...
"FieldError at /news/11
Cannot resolve keyword 'slug' into field. Choices are: body, date, id, title"
at the moment I can't find an answer, I find so much stuff that I just don't know how to mix things up. I will keep searching. Help is appreciated! Thanks for now!!! :D
According to my understanding to your problem, what you need is not to create a view function for every car you have.
Indeed, you need to create 1 template (html page) that describes your CarsCatalogue, where all the CarsCatalogues have the same structure with different information. Then the user chooses one CarsCatalogue, let's say from a dropdown control and then you load the data from your database and show your results in the template.
In order to achieve this, have a look on the following topics:
Django forms. And in order to get your data from the database, you need the the id for example to be passed in the url, you can see this answer how to pass an id in django url or from the official website URL Dispatcher.
In few words, django is a simple way to do your website and definitely no need to rewrite your code several times.
NO THERE IS NO NEED TO CREATE MULTIPLE URLS.
From what I understood, you want a catalogue for each car.
Just create a view from where you display the names of all your cars.
Then when you click on a car, make a get request to another view function in the get request pass your selected car details. Now comes the use on Django Templates. Create a Django template for your catalogue, pass the car specific data to it.
You need to read about Django Templates , I think Django templates is something that will solve your problem.
I think the thing you're missing is that the parameter in the URL can be anything, not just a numeric URL. If it's a string, we call that a slug, and the Django admin will automatically create a slug from the fields in your model if you set the prepopulated_fields option.
Then, you can use that slug in the URL:
url(r'^(?P<slug>[\w-]+)$', DetailView.as_view(
model = Car,
template_name="news/car.html"))
and Django will use that field instead of the ID to find the right content to display.
I found a way to fix my problem.
Even though I started off by asking about the CARS Catalogue, I will explain what I did using the NEWS APP instead, as the logic is the same and as that is the APP I have modified in the first EDIT of my post.
Inside the Templates, have a "news.html" page to render the list of all the Post, and a "post.html" to render every single Post.
The following is part of the procedure on how to set an APP that you can manage directly from the ADMIN PANEL, and that uses the SLUG field as URL.
models.py:
from django.db import models
class Post(models.Model):
title = models.CharField(max_length = 140)
body = models.TextField()
slug = models.SlugField(unique=True)
def __str__(self):
return self.title
admin.py:
from django.contrib import admin
from news.models import Post
class PostAdmin(admin.ModelAdmin):
model = Post
prepopulated_fields = {'slug': ('title',)}
admin.site.register(Post, PostAdmin)
urls.py:
from django.conf.urls import url
from django.views.generic import ListView, DetailView
from news.models import Post
urlpatterns = [
url(r'^$', ListView.as_view(
queryset=Post.objects.all(),
template_name="news/news.html")),
url(r'^(?P<slug>[\w-]+)$', DetailView.as_view(
queryset=Post.objects.all(),
model = Post,
template_name="news/post.html")),
]
I hope that can be useful to somebody.
Jeez you gotta study hard to use this Framework :D
Thanks everybody for the support, c ya :)
I am trying to work with Sites Model of Django.
I dont quite understand why SITE_ID should be SITE_ID = 1.
in the docs:
The ID, as an integer, of the current site in the django_site database
table. This is used so that application data can hook into specific
sites and a single database can manage content for multiple sites.
why 1? what is the current site? this is not clearly explained in the docs.
lets say, I have www.coolsite.com and some other subdomains like www.wow.coolsite.com and www.awesome.coolsite.com
I want to render different content depending on domain name.
my question is, or better, are:
Do I have to add all those domains into Sites Table in DB?
if so, how should I set SITE_ID in settings? Do I have to set all ids like SITE_ID = 1, SITE_ID = 2.. etc?
what does current site has to do with SITE_ID = 1?
I am a bit confused here.
I thought, each Site (e.g. www.wow.coolsite.com) should be a separate django project so that they can have their own settings.py? and in each of those settings.py's, I will set the id of that page from Sites table? but then there are many django projects which also doesnot make sense to me.
Django was created from a set of scripts developed at a newspaper to publish content on multiple domains; using one single content base.
This is where the "sites" module comes in. Its purpose is to mark content to be displayed for different domains.
In previous versions of django, the startproject script automatically added the django.contrib.sites application to INSTALLED_APPS, and when you did syncdb, a default site with the URL example.com was added to your database, and since this was the first site, its ID was 1 and that's where the setting comes from.
Keep in mind that starting from 1.6, this framework is not enabled by default. So if you need it, you must enable it
The SITE_ID setting sets the default site for your project. So, if you don't specify a site, this is the one it will use.
So to configure your application for different domains:
Enable the sites framework
Change the default site from example.com to whatever your default domain is. You can do this from the django shell, or from the admin.
Add your other sites for which you want to publish content to the sites application. Again, you can do this from the django shell just like any other application or from the admin.
Add a foreign key to the Site model in your object site = models.ForeignKey(Site)
Add the site manager on_site = CurrentSiteManager()
Now, when you want to filter content for the default site, or a particular site:
foo = MyObj.on_site.all() # Filters site to whatever is `SITE_ID`
foo = MyObj.objects.all() # Get all objects, irrespective of what site
# they belong to
The documentation has a full set of examples.
Things would be much easier to understand if Django's default SiteAdmin included the id field in the list_display fields.
To do this, you can redefine SiteAdmin (anywhere in your app, but I'd recommend your admin.py or maybe your urls.py) like this:
from django.contrib import admin
from django.contrib.sites.models import Site
admin.site.unregister(Site)
class SiteAdmin(admin.ModelAdmin):
fields = ('id', 'name', 'domain')
readonly_fields = ('id',)
list_display = ('id', 'name', 'domain')
list_display_links = ('name',)
search_fields = ('name', 'domain')
admin.site.register(Site, SiteAdmin)
After including this code snippet, the ID for each "Site" will be shown in the first column of the admin list and inside the form as a read only field. These 'id' fields are what you need to use as SITE_ID:
The concept is that each different site runs in a different application server instance, launched using a different yourdomain_settings.py that then includes a base_settings.py with the rest of the common configuration.
Each of these yourdomain_settings.py will define its own SITE_ID and all other different settings.py parameters that they need to look and be different from each other (static resources, templates, etc.) then you'll define a DJANGO_SETTINGS_MODULE environment variable pointing to that specific yourdomain_settings.py file when launching the application server instance for that domain.
A further note: get_current_site(request) does need request to be available for it to work. If your code doesn't have one, you can use Site.objects.get_current() that however will need a SITE_ID properly defined in the running application server's settings.
This is a late answer but for anyone else having SITE_ID issues and Site problems.
Inside the database, django has a django_site table with(id, domain, name). This is where django stores the SITE_IDs. Mine was actually 5 in the database but i had it set to SITE_ID=1 in the settings.
Knowing that, i can now go back to the database and clear it to get back to zero or use the actual id in the database.
This is covered in the documentation for the Sites framework:
In order to serve different sites in production, you’d create a
separate settings file with each SITE_ID (perhaps importing from a
common settings file to avoid duplicating shared settings) and then
specify the appropriate DJANGO_SETTINGS_MODULE for each site.
But if you didn't want to do it that way, you can not set SITE_ID at all and just look up the current site based on the domain name in your views using get_current_site:
from django.contrib.sites.shortcuts import get_current_site
def my_view(request):
current_site = get_current_site(request)
if current_site.domain == 'foo.com':
# Do something
pass
else:
# Do something else.
pass
This link explains it:
You’ll want to create separate settings files for each domain you’re adding; each one will need its own MEDIA_URL and other settings. You’ll also want to do two things to make sure everything works out properly for administering the different sites:
Create a new Site object in your admin for each domain, and put the id of that Site into its settings file as SITE_ID so Django knows which site in the database corresponds to this settings file.
In the settings file for your original site (the one with id 1), add the other sites’ settings files to the ADMIN_FOR setting, to let Django know that this one instance of the admin application will handle all of the sites.
Also, if you wanna figure out how to modify models and set the views You may take a look at this link:
https://django.cowhite.com/blog/managing-multiple-websites-with-a-common-database-in-django-the-sites-framework/
I am working through a Django tutorial at http://lightbird.net/dbe/todo_list.html . I completed Django's official tutorial. When I attempted to sync
from django.db import models
from django.contrib import admin
class Item(models.Model):
name = models.CharField(max_length=60)
created = models.DateTimeField(auto_now_add=True)
priority = models.IntegerField(default=0)
difficult = models.IntegerField(default=0)
class ItemAdmin(admin.ModelAdmin):
list_display = ["name", "priority", "difficult", "created", "done"]
search_fields = ["name"]
admin.site.register(Item, ItemAdmin)
The terminal came back with an error that said admin was not defined. What am I doing wrong? How do I define admin?
Update: I added the whole models file as it looks now
The Django documentation lists multiple steps that need to be done to activate the admin site:
Add 'django.contrib.admin' to your INSTALLED_APPS setting.
The admin has four dependencies - django.contrib.auth, django.contrib.contenttypes, django.contrib.messages and
django.contrib.sessions. If these applications are not in your
INSTALLED_APPS list, add them.
Add django.contrib.messages.context_processors.messages to TEMPLATE_CONTEXT_PROCESSORS and MessageMiddleware to
MIDDLEWARE_CLASSES. (These are both active by default, so you only
need to do this if you’ve manually tweaked the settings.)
Determine which of your application’s models should be editable in the admin interface.
For each of those models, optionally create a ModelAdmin class that encapsulates the customized admin functionality and options for
that particular model.
Instantiate an AdminSite and tell it about each of your models and ModelAdmin classes.
Hook the AdminSite instance into your URLconf. lists a couple of things that you must do the enable Django's admin site.
If you haven't done the first two items, syncdb might complain because it can't find the admin app itself.
edit: I wasn't clear before, I am saving my object in the django admin panel, not in a view. Even when I save the object with no many-to-many relationships I still get the error.
I have a model called TogglDetails that has a ForeignKey relationship with the standard django User model and a MayToManyField relationship with a model named Tag. I have registered my models with django admin but when I try to save a TogglDetails instance I get the error in the title.
Here are my models:
class Tag(models.Model):
name = models.CharField(max_length=30)
def __unicode__(self):
return self.name
class TogglDetails(models.Model):
token = models.CharField(max_length=100)
user = models.ForeignKey(User)
tags = models.ManyToManyField(Tag, blank=True, null=True)
def __unicode__(self):
return self.user.username
class Meta:
verbose_name_plural = "toggl details"
As far as I can tell, there should be no issues with my models and django admin should just save the instance without any issues. Is there something obvious that I have missed?
I am using Django 1.3
The answer to my question was this: Postgres sequences without an 'owned by' attribute do not return an id in Django 1.3
The sequences in my postgres database did not have the "Owned by" attribute set and so did not return an id when a new entry was saved to the db.
As stated by other users:
Postgres sequences without an 'owned by' attribute do not return an id in Django 1.3
The sequences in my postgres database did not have the "Owned by" attribute set and so did not return an id when a new entry was saved to the db
In addition:
This is most likely caused by a backwards incompatible change that renders some primary key types in custom models beyond reach for Django 1.3. See Django trac tickets https://code.djangoproject.com/ticket/13295 and http://code.djangoproject.com/ticket/15682 for more information.
I solved the problem by running the follow commands for the affected tables/sequences.
Specifically running the command:
manage.py dbshell
ALTER SEQUENCE tablename_colname_seq OWNED BY tablename.colname;
change tablename_colname_seq and tablename.colname
Don't let us guess and add the Error message to your question, this gives most information about where it fails.
Have you imported the User model?
from django.contrib.auth.models import User
I've had this problem as well and the only thing I could do was make the M2M fields blank and not set them until I hit Save and Continue Editing.
I think this just may be a framework wart, as you will notice the User section of the Admin site also has a very strict "You can only edit these fields until you save the model".
So my recommendation is to adopt that scheme, and hide the M2M form field until the model has a Primary Key.
I tried Django 1.3 using CPython, with different database setups. I copy-pasted the models from the question, and did some changes: first I added
from django.contrib.auth.models import User
at the top of the file and I put the reference to Tag between quotes. That shouldn't make any difference. Further, I created the following admin.py:
from django.contrib import admin
import models
admin.site.register(models.Tag)
admin.site.register(models.TogglDetails)
For Sqlite3, the problem described doesn't occur, neither for MySQL. So I tried PostgreSQL, with the postgresql_psycopg2 back end. Same thing: I can't reproduce the error.
So as far as I can figure, there's nothing wrong with the code in the question. The problem must be elsewhere.