Practical Django Projects - Pages 71 and 80 - python

I am reading the book "Practical Django Projects". It is a nice book. I have a few questions though :
On page 71, there is the following code :
from django.conf.urls.defaults import *
from django.contrib import admin
admin.autodiscover()
from coltrane.models import Entry
entry_info_dict = {
'queryset': Entry.objects.all(),
'date_field': 'pub_date',
}
...
However no variable 'pub_date' has yet been defined in that file !
On page 80, I am being told that I should place two variables DELICIOUS_USER and DELICIOUS_PASSWORD in the Django settings file. I should then call that file with
from django.conf import settings
Where is that Django settings file ? In C:\Python27\Lib\site-packages\django\conf ?

pub_date refers to coltrane.models.Entry attribute pub_date see the source
from django.conf import settings imports your project settings.py so you have to define your settings inside your project/settings.py file. Here are some docs on the official docs about using settings in python code

pub_date is referencing a field defined in the Entry model. Django will look up the field by name later, which is why it's in quotes (otherwise it would trigger an NameError).
In models.py, you should have something like:
class Entry(models.Model):
...
pub_date = models.DateField(...)
The settings file is typically called settings.py, and is located in your project's root folder (next to manage.py, etc.).

Related

Django app dissapears from Django Admin site when I add apps.py file

I'm working with Django 3.2 and trying to configure correctly the AppsConfig subclass of apps.py in order to avoid duplicate apps names when initzialing the project.
The context is the following. I have in my INSTALLED_APPS two apps whose names are equal although their paths not:
INSTALLED_APPS = [
...
'first_app.myapp',
'second_app.myapp'
]
To avoid the error shown below (and according to the documentation), I need to create an apps.py file subclassing AppConfig in at least one of the apps called myapp. I've decided to create that file in the second one, second_app.myapp.
django.core.exceptions.ImproperlyConfigured: Application labels aren't unique, duplicates: myapp
The app.py in second_app.myapp module looks like as follows:
from django.apps import AppConfig
class MySecondAppConfig(AppConfig):
name = "second_app.myapp"
label = "my_second_app"
And in the __init__.py I've added:
default_app_config = 'second_app.myapp.apps.MySecondAppConfig'
My admin.py looks like:
from django.contrib import admin
from .models import MyModel
class MySecondAppAdminModel(admin.ModelAdmin):
list_display = ('attr_1', 'attr_2')
admin.site.register(MyModel, MySecondAppAdminModel)
When I start the project all works OK and I can use that model information, views called from second_app.myapp also work OK.
The problem comes when I access to the admin site (http://localhost:8000/admin), where only appears the first_app.myapp admin form instead of both.
Can you help me? Thanks in advance.
instead of this:
INSTALLED_APPS = [
...
'first_app.myapp',
'second_app.myapp'
]
Just try this way only:
INSTALLED_APPS = [
...
'first_app',
'second_app'
]
You got that error because here first_app.myapp and second_app.myapp myapp is duplicate. you should not use like this in both the apps.
OR
INSTALLED_APPS = [
...
'first_app.apps.MyFirstAppConfig',
'second_app.apps.MySecondAppConfig'
]

Permission does not show in admin page

I have added an app to my existing django site and to view it, I created an extra permission overview.view. But, I do not see it in my admin page, so I can also not assign this permission to any user. I think I have all files setup correctly, but I guess I am missing something. I have all the same files in the overview folder as I have in other working folders.
I do see the page, but somehow I am not logged in either.
This is my urls.py:
from django.urls import path
from . import views
urlpatterns = [
path('', views.index, name='index')
]
models.py:
from django.db import models
class Overview(models.Model):
class Meta:
permissions = (
('view', "May view the overview"),
)
and (part of) settings.py
INSTALLED_APPS = [
'overview.apps.OverviewConfig'
]
Permissions are stored in the database and so when you add or remove them via the Meta for the model the same is not of course automatically reflected in the database. Permissions are added post the migrations via a post_migrate signal connected from the auth apps appconfig's ready method. See the source code [GitHub]:
post_migrate.connect(
create_permissions,
dispatch_uid="django.contrib.auth.management.create_permissions"
)
Hence when one makes changes to the permissions one needs to run makemigrations and migrate to make sure they are added to the database.

Django-ajax-selects with AJAX_SELECT_BOOTSTRAP = False

At work we are using django-admin webapp. I wanted to implement django-ajax-selects functionality to some of fields. Our network is isolated from Internet and I cannot use django-ajax-selects's CDNs. Documentation says that in such case you should set AJAX_SELECT_BOOTSTRAP to False in settings.py file. However, when I set this parameter, django-ajax-selects fails to use django's jquery.
Django's version is 1.11.10, Python2.
Steps to reproduce my issue:
pip install django==1.11.10 django-ajax-selects
django-admin startproject proj ./
python manage.py startapp test_app
python manage.py migrate
python manage.py createsuperuser
test_app/models.py
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models
class Tag(models.Model):
name = models.CharField(max_length=100)
something = models.CharField(max_length=100)
def __str__(self):
return self.name
class SecondModel(models.Model):
name = models.CharField(max_length=200)
tag = models.ForeignKey(Tag, on_delete=models.CASCADE)
def __str__(self):
return self.name
test_app/lookups.py
from ajax_select import register, LookupChannel
from .models import Tag
#register('tags')
class TagsLookup(LookupChannel):
model = Tag
def get_query(self, q, request):
return self.model.objects.filter(name__icontains=q)
def format_item_display(self, item):
return u"<span class='tag'>%s</span>" % item.name
test_app/admin.py
# -*- coding: utf-8 -*-
from django.contrib import admin
from ajax_select import make_ajax_form
from .models import Tag, SecondModel
#admin.register(Tag)
class TagAdmin(admin.ModelAdmin):
fields = ['name', 'something']
#admin.register(SecondModel)
class SecondModelAdmin(admin.ModelAdmin):
form = make_ajax_form(SecondModel, {
'tag': 'tags'
})
proj/settings.py - adding the app and ajax_select to INSTALLED_APPS
INSTALLED_APPS = (
...
'ajax_select',
'test_app',
)
proj/urls.py
from django.conf.urls import url, include
from django.contrib import admin
from ajax_select import urls as ajax_select_urls
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^ajax_select/', include(ajax_select_urls)),
]
Then
python manage.py makemigrations test_app
python manage.py migrate
If I run the server like that it works absolutely fine (because it uses CDNs to load jquery and stuff).
But if I set AJAX_SELECT_BOOTSTRAP to False I will get a TypeError in browser's console and the ajax functionality will not work. I guess ajax_select.js just loads before django's jquery was loaded. I could not figure it out, how can I specify load order or may be there is another way? Template overriding would be not very good idea as there is some overriding already used by other apps and I'm afraid it can cause some conflicts.
In the end what I needed to do was to manually download jquery.min.js, jquery-ui.js, jquery-ui.css and also jquery-ui images library, put them into app's static directory and point to them in admin.py:
admin.py
...
#admin.register(SecondModel)
class SecondModelAdmin(admin.ModelAdmin):
form = SecondModelForm
class Media:
js = ["/static/js/jquery.min.js",
"/static/js/jquery-ui.js"]
css = {'all': ["/static/css/jquery-ui.css"]}
Also don't forget to run python manage.py collectstatic for static files to be copied to common static directory.

Add view in the bottom of Django modeladmin

I have a blog made with Django where I write posts in markdown. I would like to add a view in the bottom of the admin page for each instance of the class Entry (my blog post class) such that I can get a preview of what the markdown looks like, while I'm writing. Just as you get a preview here on Stack Overflow when you create a new post.
I already have an admin class extending ModelAdmin:
class EntryAdmin(admin.ModelAdmin):
list_display = ('title','created')
prepopulated_fields = {'slug': ('title',)}
Is it possible to modify ModelAdmin further, such that it loads a certain html file (blogpost.html) and shows it in the bottom of the admin page?
I made a picture to show exactly what I mean:
NB: I know there are various tools such as Django admin plus, that allows one to add views to the admin interface, but not for each instance of an object.
You can use markdownx for that:
pip install django-markdownx
project settings.py
INSTALLED_APPS =
#. . . .
'markdownx',
]
project urls.py
urlpatterns = [
#[...]
url(r'^markdownx/', include('markdownx.urls')),
]
and then collect static files.
python3 manage.py collectstatic
your models.py
from markdownx.models import MarkdownxField
class MyModel(models.Model):
myfield = MarkdownxField()
your app admin.py
from django.contrib import admin
from markdownx.admin import MarkdownxModelAdmin
from .models import MyModel
admin.site.register(MyModel, MarkdownxModelAdmin)
This should work.

How to change django admin "view site" link to custom absolute url

I have REST API built on Django and JS application. Both are on different domains. How to change django admin "VIEW SITE" link in such way so it will open JS application? I've tried to pass absolute link (https://docs.djangoproject.com/es/1.10/ref/contrib/admin/#django.contrib.admin.AdminSite.site_url), but looks like it does not work - only relative paths allowed
I prefer resetting admin.site.site_url in urls.py, along with other site changes (instead of doing this in an admin.py file, cause a project can have serveral admin.py)
# urls.py
admin.site.site_url = '' # Removes the 'View Site' link
admin.site.site_header = 'My Site'
In Django 1.11.5, it seems that :
from django.contrib import admin and
admin.site.site_url = 'https:....' in the admin.py file is enough
By default , "VIEW SITE" points to '/' i.e localhost:8000 (Default settings assumed).
To change it , use (in admin.py):
admin.site.site_url = "/mySite"
Tested on Django 2.1
There are two solutions I can come up with.
Firstly, you could use custom template admin/base.html. But, reading through the default template, you would have to copy-paste a lot of code just to change a link, which seems like an overkill.
Another solution involves overriding AdminSite. AdminSite has a property called site_url, and it seems like changing it would do the job. So, in essense, you can do something like this:
your_app/admin.py
from django.contrib.admin import AdminSite
from .models import MyModel
class MyAdminSite(AdminSite):
site_url = 'https://yourdomain.com'
admin_site = MyAdminSite(name='myadmin')
your_project/urls.py
from django.conf.urls import url
from myapp.admin import admin_site
urlpatterns = [
url(r'^myadmin/', admin_site.urls),
]
And you should register all your models with your custom admin, not Django's default:
from your_app.admin import admin_site
admin_site.register(MyModel)
Default link to viewsite is http://127.0.0.1:8000/
We can change it to custom url through register it in admin.py
admin.site.site_url = "/mySite"
Example : admin.py
from django.contrib import admin
from auth_app.models import profile
# Register your models here.
admin.site.register(profile)
#register link
admin.site.site_url = "/mySite"
In admin.py, mention your custom path like following
admin.site.site_url = "/<Your Path>"
If your custom url is like "https://example.com/dashboard", You have to put below line in your admin.py
admin.site.site_url = "/dashboard"
You can change "VIEW SITE" link by changing "admin.site.site_url" which is "/" by default:
from django.contrib import admin
print(admin.site.site_url) # /
admin.site.site_url = "/example"

Categories

Resources