django extending an app to allow non authenticated votes - django

I have been testing a few django voting apps and found qhonuskan-votes. I have managed to install it and is works great. However, I also want it allow voting rights to non authenticated users which I am not able to do. Need help with this please.
Here is the link for its models.py, views.py and compact.py files of this app.
models
views
compact

You could write a custom view which would look like def vote(request, model, object_id, value) from the external app, but without this piece of code in it:
if not request.user.is_authenticated():
return HttpResponse(status=401)
Also make sure, that you map your custom view to the correct url instead of including app's urls:
url(r'^vote/$', view='custom_vote', name='qhonuskan_vote'))
This is not the best solution, because you are simply rewriting the code from the external app and I can't think of any proper way to override the default view in a way that would suit your needs. A better solution would be to use a different app, which allows votes by unauthenticated users (if a few lines of additional code are not a problem you can use this).

Related

How can I change the view site link in Django admin, depending on which app is used?

I am making a project where each client have their own app. This is because they have similar pages but not exactly the same so I think it's a good approach(I may be wrong) to just copy one app for each new client. I have not tried it yet, I am still planning for it. I see one problem with the view site link in the admin. I will let the clients use the admin. How can I set the view site link to the main page for the client? One way to solve it would be to leave it as is and have a function checking their user name and redirecting to the right app. But is there any other way to solve this problem?
I don't think it will be a good idea to have applications generated for users as that's too much once you reached a specific amount of users.
they have similar pages but not exactly the same
Then what you should do is to, after getting the user in your view, pass in a different context to your template. Something like:
def my_view(request):
# First assign different context to different users
context = {'data': 'whatever each user gets', 'other': 'put in more than 1 data',}
return render(request, 'myapp/index.html', context)
I will let the clients use the admin
That's not a good idea as the clients MUST be a superuser to view the admin site. Otherwise, you need to change the permissions of a superuser, make a separate superuser if you are the maintainer of the site, and all sorts of trouble. Just take some time and make your own templates.

Set user permissions for specific views in Django

I am using Django to make a website with a bunch of different pages. I only have views, I have not defined any models in my project. I want certain users to have restricted access (they can only see some of the views I've created). I've set up some users in the Django admin site and added login functionality to my website using the Python #login_required decorator.
I'm a little lost on how to set viewing permissions for each user though. I've looked at the #permission_required decorator but it seems to only pertain to models and not views. How do you set page viewing permissions in Django?
Permissions are linked to models. If your authorization logic is linked to the view and not to a model, consider creating a group and using the user_passes_test decorator. For example, lets say you have a report that only supervisors can see: create a group named Supervisors and test for membership:
def must_be_supervisor(user):
return user.groups.filter(name='Supervisors').count()
#user_passes_test(must_be_supervisor)
def quarter_report(request):
...
You should use user_passes_test decorator for views. Django documentation has a nice example of it's usage
https://docs.djangoproject.com/en/1.8/topics/auth/default/#django.contrib.auth.decorators.user_passes_test
Edited: actually you can use permission_required decorator for views also
https://docs.djangoproject.com/en/1.8/topics/auth/default/#django.contrib.auth.decorators.permission_required
Take a look at django-braces. It's a superb app for exactly this purpose;
https://django-braces.readthedocs.org/en/latest/index.html
It provides a mixin for almost every eventuality for use in views & forms which allow you to perform checks to restrict access how you see fit.
you can use permission_required in urls to lock
example: https://docs.djangoproject.com/en/3.2/topics/class-based-views/intro/#decorating-in-urlconf

Django - permission_required on view level

I am looking at the built-in authentication functionality from Django for my custom app.
If I understand this right, I can assign add, change, delete rights to models.
I am looking for a solution to assign view/show rights to a user.
My basic idea is to use the permission_required decorator for this, but as stated this only works for add, change, delete and in addition it seems only to work for models. I have functions where I am using multi-objects from models.
The best would be to have something that collects my custom permission_required decorators and gives me the possibility to edit this e.g. in the Django admin UI.
E.g.
#permission_required('user.profile.view')
def myProfile(request):
...
#permission_required('user.profile.edit')
def editMyProfile(request):
...
Any idea or suggestion is welcome.
Thanks in advanced!
Creating custom permissions is well documented. Once you've created custom permissions, you'll be able to assign them to users through the usual user admin page.

django: modifying/extending 3rd party apps

a newbie django question
I want to use 3rd party app, but I need to make some mods to it (in this case, the app is django-registration, and I need to change things such as allowing registration without confirmation email)
Initially, I simply installed the app in the general site-packages folder, and changed the code there. Now that I put my code on bitbucket I need a way to be able to keep my mods in the repository in a usable way, and uploading the full python code doesn't sound like a good idea.
I guess the best way would be to keep the 3rd party app in site-packages, and create an app in my project to keep my changes. In my case, I'd create my-django-registration in my project, and then import this when I need it in my code, rather than django-registration.
I also read about virtualenv, but I think that's mostly used for being able to use multiple environments in the same machine (in fact, somewhere it advises against changing the modules installed in the virtualenv), and doesn't help me with keeping my changes in a repository.
Any comments welcome!
Thanks
In general, you should reuse and override the behavior in 3rd party apps and not modify their sources.
What you'll most often encounter is that apps ship models that may not necessarily cover your needs, but do most of the work; you'll have forms that are almost perfect, but need that little something; you'll have views that would be perfect if you can just change one thing; you'll have URLs that are sane, but you need something more from them.
In most cases, that would just require that you create a custom app and rewire everything. Ship your own URLs that map to views that you've extended and overrode methods for custom behavior; supply it with a model form who's Meta is using the new model that you've extended from the original; so forth...
That's just the tip of the iceberg of what you can do, there's more ways when your creative. I can give you an example of how I've used the RegistrationProfile model, but shipped my own URL patterns and a custom class-based view that handled the registration process.
Now, where virtualenv comes into play is that you'll most likely be using pip to specify and supply your required dependencies in the requirements file format. That's when you want to say: "I've extended the django-registration app, but it won't work cleanly with just any version. It has to be of release X", or , "a checkout from the repository of commit Y".
This blog post that adresses this issue is extremely helpful. For convenience I copy-paste it here:
You don’t touch external app code
You are not supposed to edit the code from an external app. Unless you fork it first on github.
So, how to override without forking:
Overriding a template
If you want to override templates/userena/activate_fail.html, then all you have to do is create your own templates/userena directory and make your own activate_fail.html in it.
Overriding a url
Probably the first thing you should check in an external app is its urls.py. Views that are properly coded should support plenty of arguments. For example, userena has a signup view with such a signature (at the time of writing):
def signup(request, signup_form=SignupForm,
template_name='userena/signup_form.html', success_url=None,
extra_context=None):
This means that you can replace the form used by the signup view. To do so, open your urls.py, add what we are going to need at the top:
from userena import views as userena_views
from yourforms import YourSignupForm
Then, find the include the external app’s urls, something like:
url(r'^userena/', include('userena.urls')),
Before that, add your url override:
url(r'^userena/signup/$', userena_views.signup, {'signup_form': YourSignupForm}, name='userena_signup'),
url(r'^userena/', include('userena.urls')),
Now, your custom url definition will be the first to be hit when a visitor hits /userena/signup/. Which means that /userena/signup/ will use YourSignupForm instead of userena’s signup form.
This trick works with any view argument. The ones you should see the most often are:
template_name: lets you change the template name
extra_context: lets you add a dict that will be added to the
context
Almost every view should have these arguments.
Overriding a view
Overriding a view requires to override the url of the view you want to replace. If you want your own signup view to be used, then just override the url:
import yourviews
# ...
url(r'^userena/signup/$', yourviews.yoursignup, name='userena_signup'),
url(r'^userena/', include('userena.urls')),
Decorating a view
Decorating a view is like overriding a view, but reuses the external app’s view. Basically, it’s the same than overriding a view (see above), but your view will look like this
from userena import views as userena_views
def yoursignup(request):
# do stuff before userena signup view is called
# call the original view
response = userena_views.signup(request)
# do stuff after userena signup view is done
# return the response
return response
Forking an app
If you are not familiar with pip and virtualenv first, please read the post about using pip and virtualenv first.
For example:
You installed django-userena as such: pip install django-userena
First you should uninstall it: pip uninstall django-userena
Then go on the app’s github page
Click on the fork button
This will make you a repository with a copy of django-userena
Install it as such: pip install -e
git+git#github.com:your-username/django-userena.git#egg=django-userena
Then you can edit the code in yourenv/src/django-userena
Push your commits
Credits to the post writer!
I think the neatest way to accomplish what you look for would be to fork django-registration, and in your app use the fork instead of the original project.
That being said, you can have a non-email registration in django-registration without changing the code of the app. I've done it by creating a custom registration backend that sets the users as activated upon creation. Here you can see other ways to do the same.

Django options for making variables widely available

Every time I open a page I want to get the currently active project id. This will be done by chacking the subdomain and verifying the currently logged in user can view it.
Once I reach my view I want to be able to do
tasks = Task.objects.filter(project = current_project)
WHere current_project (or CURRENT_PROJECT or current_project ???) has already been setup.
Can anyone explain the pros/cons of the various approaches I have found in the docs and put me on the right track?
Sessions
Middleware
Threading
builtins
This was how I did it in the end:
Decorator:
def check4project(fn):
current_project = 'fred'
def check(*args, **kw):
kw['project']=current_project
return fn(*args, **kw)
return check
View example
#login_required
#check4project
#tweetpost
def index(request, project=0):
print project
It all depends on what your semantics of "current project" are. Here are some possibilities:
It could be a characteristic of the user: he visits his profile page and sets a current project. This would be stored in the database, and you would access it with the ORM.
It could be a characteristic of the URL, based solely on subdomain. This could be done with middleware, which has access to the request, and could for example, parse the host name and set a custom attribute on the request that you could access in your view functions.
Similar to #2, you could use a view decorator if checking projects is done for some views but not all. This is similar to Django's decorators for checking authorization.
It could be a characteristic of the user's visit to the site: he visits a page of projects, chooses one to work on, and it's sticky until he chooses another project. This would be best stored in the session, which is specifically for this sort of transient storage.
From your description, it sounsd like #2 or #3 is the best for you, depending on how your views divide up between caring about subprojects and not.
You could make a context_processor and then get your value from the request object.
Have you considered a custom template tag?