Get the site_id of the user_id in Django? - django

I'm really struggled by this. I looked through the Django documentation and I couldn't find a method to get the site_id of the currently logged in user_id with Sites framework.
I want to build a blogpost form and I wan't to include the site_id so that the content that the user publish will go to that particular site_id.
The user will only have permissions to publish to one site_id.
To clarify:
Publish content to the site_id that the user_id belongs to.
Is there a way to do this?

A user does not belong to a site. A request does.
If, somehow, in your Django project sites are owned by users, then you should add a new field to your User model. Something like this:
class MyUserModel(...):
...
blog = models.OneToOneField(Site)

Related

In django admin panel permissions given to the users by group not working

In Django admin panel
I create groups and give permission to them.
eg:
Create a Student Group and give it permission to view the student model.
Create a Teacher Group and give it permission to view the student model and add the student model.
create user using API and added to those groups,
and also staff status checked for each user.
When users log in on the admin panel that shows Site administration You don’t have permission to view or edit anything.
How to solve it.
I've got the same issue, tried every solution out there but they're all either outdated or not useful to my case. First let me ask you some questions.
1- What version of django are you using?
2- Do you have ModelBackend set in your AUTHENTICATION_BACKENDS like that?
AUTHENTICATION_BACKENDS = [
...
"django.contrib.auth.backends.ModelBackend",
...
]
3- If you're using a custom user model, have you extended PermissionsMixin in your class like that?
class CustomUser(AbstractBaseUser, PermissionsMixin):
# Fields
If you've done all of that and still stuck at it, like myself, then i'm not really sure what could help us. Anyway, i'll keep you posted if i get to know anything else.

User registration with admin authorization

I was wonder if it is possible to include a way that when someone fill the user registration form to register, can the details be sent to an admin email for authorization before the user can login in django?
Since you did not provide any code I will guide you the process, you can later come back more specific question if you are stuck :
Use the field is_active provided by Django from the User model to authorised access within your website.
Extends the field is_active to set the default to False or set it to false in the begging of your user view
Create a link with the ID of the user and a path to the Django Admin where you can update the user and active to True
In short yes, possible and pretty easy if you know a bit of Django.

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/

Django 'Sites' Model - what is and why is 'SITE_ID = 1'?

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/

In the Django admin, is there a way to show a list of actual links to a model's one-to-many objects?

If this is too complicated or not the right way to do things, feel free to link me to something else or just tell me I should do it another way...
Basically, I'm working on a project where there are Clients, and each one has an arbitrary number of Websites attached to it. So the Websites model has a ForeignKey to the Client model. The Website admin page is pretty in-depth, and each Client might have 10 or more sites, so I'd rather not have them all display as inlines, because that's really messy and crazy looking.
What I'd like is that when you go to the admin panel and click Clients, you're brought to the change page where it has the basic stuff you'd edit for the client and then an inline of actual links to each of the client's website admin pages. Like this:
Change client
General
Name:
Address:
Phone:
Websites
Link to edit Website 1
Link to edit Website 2
Link to edit Website 3
Link to edit Website 4
Link to edit Website 5
You can use a TabularInline that includes only a link to the model change page:
class ClientAdmin(admin.ModelAdmin):
# everything as normal
inlines = WebsiteInline,
class WebsiteInline(admin.TabularInline):
model = Website
fields = 'link',
readonly_fields = 'link',
def link(self, instance):
url = reverse("admin:myapp_website_change", args = (instance.id,))
return mark_safe("<a href='%s'>%s</a>" % (url, unicode(instance)))
admin.site.register(Client, ClientAdmin)
admin.site.register(Website)
See my recent question How do I add a link from the Django admin page of one object to the admin page of a related object? which was about how to do exactly this, but with several pairs of models rather than just one.