django reversing admin urls with underscores - django

To reverse a model url for Django Admin, you need to write admin:appname_modelname_change . But what if the model name has underscores?
I have a model called AdNetwork inside an app called pubscout, and I am trying to reverse its url.
admin:pubscout_adnetwork_change doesn't work
admin:pubscout_ad_network_change doesn't work either
How to fix this?

Please can you show us your code.
reverse('admin:%s_%s_change' % (app_label, model_name), args=(object_id,))
Something like this should work:
reverse('admin:pubscout_adnetwork_change', args=(object_id,))
... where object_id is an AdNetwork pk.
Please make you have registered the AdNetwork model and hooked the AdminSite instances into your URLconf.
Docs: https://docs.djangoproject.com/en/1.9/ref/contrib/admin/#reversing-admin-urls

Related

django_currentuser alternatives or how to get current user in Models.py

I have 2 Models in my django models.py.
I need to get data from model2 to model1, but I don't need to store it anywhere in the model1 fields. I found #property of django and implemented that. My issue was that I need to get who the user is using request.user, which is not possible in models.py
So how can I access user in django models? Is there any other packages? or is there any inbuilt django way which I haven't thought about?
I searched and got a package called django-currentuser , unfortunately i'm using Django 4 which doesn't have a support.
I didn't get exactly what's your problem.
if you want to get the current user in django,this should be handled in your views like:
def View(request):
user = request.user
and if the other model that you got data from have any field connected to User like:
user = models.Foreignkey(User,...)
you can easily achive the user...
please describe more...

How to edit the Django Admin User social auths listing page?

I am having trouble finding where this admin file exists so I can add an extra field. I think it's auto-magically created upon setup.
I want to add a date field, specifically, to the listing page (shown below), perhaps after the UID field so I can know when the user auth was created.
screenshot of django user social auths listing page
Okay here's what I've tried using Django-allauth and I think it somehow works the same with django-socialauth. Just get the gist of the idea and work it to your code
Extend first the SocialAccountAdmin in any of your admin.py files, better if in a specific app like "user", "home", or whatever you prefer.
admin.py
from allauth.socialaccount.admin import SocialAccountAdmin
from allauth.socialaccount.models import SocialAccount
class MySocialAccount(SocialAccountAdmin):
list_display = ('user', 'uid', 'provider', 'date_joined') # I haven't tried just adding a certain list to the list_display, for the meantime add all necessary fields just like how socialauth did
admin.site.unregister(SocialAccount) # Need to unregister the default socialaccount admin
admin.site.register(SocialAccount, MySocialAccount) # Then register it back with the custom made admin
There may be perhaps a better way to do this but this did the work.
Can it be interesting to just add a field to your model ? Adding a DateField for your creation date. Probably you need to understand learn more with : https://docs.djangoproject.com/en/3.0/ref/models/fields/

Using Django for a very simple website: is it worth it?

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 :)

Django admin filter

I've got multiple instances of a model, and each instance has a related email address. However, several instances have the same connected email address but when I put filter['email'] into my admin.py, I get a long list of the instances' emails, i.e. multiple copies of the same email in several cases.
Is there a way I can remove emails being listed multiple times? Or a way of customising the filter view into something a little nicer? (drop down menu maybe?)
I don't have a ManyToManyField relationship currently, or anything like that. I just have instances in my database with the fields name and email. My models.py looks like this:
import ldapdb.models
from ldapdb.models.fields import CharField, IntegerField, ListField
class Item(ldapdb.models.Model):
item = CharField(db_column='item', max_length=30, primary_key=True, unique=True)
email = CharField(db_column='mail', max_length=20)
My admin.py looks like so:
from items.models import Item
from django.contrib import admin
class ItemAdmin(admin.ModelAdmin):
readonly_fields = ('email',)
list_display = ('item', 'email')
list_filter = ['email']
search_fields = ['item']
admin.site.register(Item, ItemAdmin)
Obviously I've been looking at https://docs.djangoproject.com/en/1.3/ref/contrib/admin/ but I can't really see much by the way of customising my admin's filter view.
Can you post some of your code? I'm not entirely sure I understood the relationship between the instances to your email - is it an email field? a ForeighKey to a different model? how is there more than one if it's not a ManyToMany or similar relationship? And how is the filtering done in the admin?
EDIT
Ok now I understand the problem. What you want is not possible. See for the django admin site the fact that they are the same email doesn't matter because it's still a different object. There's no way around that without either specifying that field to be unique or messing with the admin site code.
A better solution would be to configure the email as searchable in the admin model and then when you search for email example#example.com it would bring all matches back.
Another good solution is to make email a different model and link it to the Item model through a ManyToMany relationship. Then you create an EmailAdmin with a method that shows you all related items for each email.
It all depends on what you actually need. Ultimately you might want to write your own view or mess around with the admin site to modify it to what you need.
Also, you might want to change the email from CharField to EmailField. Hope this helps!

New URL on django admin independent of the apps

I am using django 1.4 and Python 2.7.
I just have a simple requirement where I have to add a new URL to the django admin app. I know how to add URLs which are for the custom apps but am unable figure out how to add URLs which are of the admin app. Please guide me through this.
Basically the full URL should be something like admin/my_url.
UPDATE
I want a way after which I can as well reverse map the URL using admin.
+1 for Jingo's answer to your original question. With your clarifying comment to the answer in mind:
Such a URL is not "independent of the apps", it is a URL for the app "admin".
Adding a URL to the admin site is similar to ModelAdmin, by overriding get_urls():
https://docs.djangoproject.com/en/dev/ref/contrib/admin/#adding-views-to-admin-sites
EDIT:
https://docs.djangoproject.com/en/dev/ref/contrib/admin/#django.contrib.admin.AdminSite
is an admin site, by default "the" admin site is instantiated as "django.contrib.admin.site" (and then e.g. your ModelAdmin's are registered against that). So you can subclass AdminSite for your own MyAdminSite and re-define get_urls() there:
from django.contrib.admin import AdminSite
class MyAdminSite(AdminSite):
def get_urls():
...
...
my_admin_site = MyAdminSite()
...
my_admin_site.register(MyModel, MyModelAdmin)
Make sure you use my_admin_site in urls.py instead now:
https://docs.djangoproject.com/en/dev/ref/contrib/admin/#hooking-adminsite-instances-into-your-urlconf
Regarding the actual contents of get_urls(),see
https://docs.djangoproject.com/en/dev/ref/contrib/admin/#django.contrib.admin.ModelAdmin.get_urls
(of course calling super() of MyAdminSite). Also note the convenient "admin_view" wrapper mentioned there.
P.S.: In theory, you could also just define get_urls() and then monkeypatch the default admin site so that it uses your get_urls() but I don't know if that would actually work - you'd probably have to monkeypatch right after its "first" import...
Just put your desired url mapping before the admin mapping in your root urls.py. The first match for the request will be taken, because django goes the url mappings from top to down. Just remember that you don't use an url the admin normally needs or provides because this will never match with a custom mapping in front of it. HTH!