Once you add http_method_names, you will not be able to do put and patch anymore.
If you want put but don’t want patch, you can keep http_method_names = ['get', 'post', 'head', 'put']
Internally, DRF Views extend from Django CBV. Django CBV has an attribute called http_method_names. So you can use http_method_names with DRF views too.
from rest_framework import viewsets, statusfrom rest_framework.response importResponseclassNameWhateverYouWantViewSet(viewsets.ModelViewSet):def create(self, request):
response ={'message':'Create function is not offered in this path.'}returnResponse(response, status=status.HTTP_403_FORBIDDEN)def update(self, request, pk=None):
response ={'message':'Update function is not offered in this path.'}returnResponse(response, status=status.HTTP_403_FORBIDDEN)def partial_update(self, request, pk=None):
response ={'message':'Update function is not offered in this path.'}returnResponse(response, status=status.HTTP_403_FORBIDDEN)def destroy(self, request, pk=None):
response ={'message':'Delete function is not offered in this path.'}returnResponse(response, status=status.HTTP_403_FORBIDDEN)
Although it’s been a while for this post, I suddenly found out that actually there is a way to disable those functions, you can edit it in the views.py directly.
from rest_framework import viewsets, status
from rest_framework.response import Response
class NameThisClassWhateverYouWantViewSet(viewsets.ModelViewSet):
def create(self, request):
response = {'message': 'Create function is not offered in this path.'}
return Response(response, status=status.HTTP_403_FORBIDDEN)
def update(self, request, pk=None):
response = {'message': 'Update function is not offered in this path.'}
return Response(response, status=status.HTTP_403_FORBIDDEN)
def partial_update(self, request, pk=None):
response = {'message': 'Update function is not offered in this path.'}
return Response(response, status=status.HTTP_403_FORBIDDEN)
def destroy(self, request, pk=None):
response = {'message': 'Delete function is not offered in this path.'}
return Response(response, status=status.HTTP_403_FORBIDDEN)
回答 3
如果尝试从DRF视图集中禁用PUT方法,则可以创建一个自定义路由器:
from rest_framework.routers importDefaultRouterclassNoPutRouter(DefaultRouter):"""
Router class that disables the PUT method.
"""def get_method_map(self, viewset, method_map):
bound_methods = super().get_method_map(viewset, method_map)if'put'in bound_methods.keys():del bound_methods['put']return bound_methods
If you are trying to disable the PUT method from a DRF viewset, you can create a custom router:
from rest_framework.routers import DefaultRouter
class NoPutRouter(DefaultRouter):
"""
Router class that disables the PUT method.
"""
def get_method_map(self, viewset, method_map):
bound_methods = super().get_method_map(viewset, method_map)
if 'put' in bound_methods.keys():
del bound_methods['put']
return bound_methods
By disabling the method at the router, your api schema documentation will be correct.
回答 4
如何在DRF中为ViewSet禁用“删除”方法
classYourViewSet(viewsets.ModelViewSet):def _allowed_methods(self):return[m for m in super(YourViewSet, self)._allowed_methods()if m notin['DELETE']]
class YourViewSet(viewsets.ModelViewSet):
def _allowed_methods(self):
return [m for m in super(YourViewSet, self)._allowed_methods() if m not in ['DELETE']]
P.S. This is more reliable than explicitly specifying all the necessary methods, so there is less chance of forgetting some of important methods OPTIONS, HEAD, etc
P.P.S.
by default DRF has http_method_names = ['get', 'post', 'put', 'patch', 'delete', 'head', 'options', 'trace']
path('sample/',SampleViewSet.as_view({'get':'list','post':'create'})),
path('sample/<pk>/',SampleViewSet.as_view({# for get sample by id.'get':'retrieve'}))
如您所见,上述路由设置中没有no delete和putrequest,因此例如,如果您将put请求发送到url,它将以405响应您Method Not Allowed:
In Django Rest Framework 3.x.x you can simply enable every each method you want to be enabled for ModelViewSet, by passing a dictionary to as_view method. In this dictionary, the key must contain request type (GET, POST, DELETE, etc) and the value must contain corresponding method name (list, retrieve, update, etc). For example let say you want Sample model to be created or read but you don’t want it to be modified. So it means you want list, retrieve and create method to be enable (and you want others to be disabled.)
All you need to do is to add paths to urlpatterns like these:
path('sample/', SampleViewSet.as_view({
'get': 'list',
'post': 'create'
})),
path('sample/<pk>/', SampleViewSet.as_view({ # for get sample by id.
'get': 'retrieve'
}))
As you can see there’s no delete and put request in above routing settings, so for example if you send a put request to the url, it response you with 405 Method Not Allowed:
Every parameter that’s passed to the as_view method is an instance variable of the View class. That means to add slug as a parameter you have to create it as an instance variable in your sub-class:
# myapp/views.py
from django.views.generic import DetailView
class MyView(DetailView):
template_name = 'detail.html'
model = MyModel
# additional parameters
slug = None
def get_object(self, queryset=None):
return queryset.get(slug=self.slug)
That should make MyView.as_view(slug='hello_world') work.
If you want to add an object to the context for the template you can override get_context_data and add to its context. The request is also a part of self in case you need the request.user.
def get_context_data(self, **kwargs):
context = super(MyTemplateView, self).get_context_data(**kwargs)
if 'slug' in self.kwargs:
context['object'] = get_object_or_404(MyObject, slug=self.kwargs['slug'])
context['objects'] = get_objects_by_user(self.request.user)
return context
In this case the parameters passed to the view should not necessarily be instance variables of the View class. Using this method you don’t need to hardcode default page name into YourView model, but you can just pass it as a parameter from urlconf.
# If slug is optionaldef the_function(self, request, slug=None):# use slug here# if slug is an optional param among othersdef the_function(self, request,**kwargs):
slug = kwargs.get("slug",None)
other_param = kwargs.get("other_param",None)# If slug is requireddef the_function(self, request, slug):# use slug here
I just wanted to add how to use it from the view. You can implement one of the following methods:
# If slug is optional
def the_function(self, request, slug=None):
# use slug here
# if slug is an optional param among others
def the_function(self, request, **kwargs):
slug = kwargs.get("slug", None)
other_param = kwargs.get("other_param", None)
# If slug is required
def the_function(self, request, slug):
# use slug here
None, False and True all are available within template tags and filters. None, False, the empty string ('', "", """""") and empty lists/tuples all evaluate to False when evaluated by if, so you can easily do
{% if profile.user.first_name == None %}
{% if not profile.user.first_name %}
A hint: @fabiocerqueira is right, leave logic to models, limit templates to be the only presentation layer and calculate stuff like that in you model. An example:
# someapp/models.py
class UserProfile(models.Model):
user = models.OneToOneField('auth.User')
# other fields
def get_full_name(self):
if not self.user.first_name:
return
return ' '.join([self.user.first_name, self.user.last_name])
# template
{{ user.get_profile.get_full_name }}
Using path() you can also pass extra arguments to a view with the optional argument kwargs that is of type dict. In this case your view would not need a default for the attribute project_id:
If you have multiple URL definitions then you’ll have to name each of them separately. So you lose the flexibility when calling reverse since one reverse will expect a parameter while the other won’t.
Another way to use regex to accommodate the optional parameter:
Then in Visual Studio Code goto: User Settings (Ctrl + , or File > Preferences > Settings if available ) Put in the following (please note the curly braces which are required for custom user settings in VSC):
@tieuminh2510 answer is perfect. But in newer versions of VSC you will not find thhe option to edit or paste that command in User Settings.
Now in newer version to add that code follow this steps :
Press ctr+sft+P to open the the Command Palette. Now in command palette type Preferences: Configure Language Specific Settings.
Now select Python. Here in right side paste this code
That’s not an error, it’s just a warning from VSC. Django adds that
property dynamically to all model classes (it uses a lot of magic
under the hood), so the IDE doesn’t know about it by looking at the
class declaration, so it warns you about a possible error (it’s not).
objects is in fact a Manager instance that helps with querying the DB.
If you really want to get rid of that warning you could go to all your
models and add objects = models.Manager() Now, VSC will see the
objects declared and will not complain about it again.
I’ve tried all possible solutions offered but unluckly my vscode settings won’t changed its linter path. So, I tride to explore vscode settings in settings > User Settings > python. Find Linting: Pylint Path and change it to “pylint_django”. Don’t forget to change the linter to “pylint_django” at settings > User Settings > python configuration from “pyLint” to “pylint_django”.
But after that, you will notice a lot of new linting errors. Then, read what it said here:
These arguments are passed whenever the python.linting.pylintUseMinimalCheckers is set to true (the default). If you specify a value in pylintArgs or use a Pylint configuration file (see the next section), then pylintUseMinimalCheckers is implicitly set to false.
What I have done is creating a .pylintrc file as described in the link, and then, configured the following parameters inside the file (leaving the rest of the file untouched):
By doing Question = new Question() (I assume the new is a typo) you are overwriting the Question model with an intance of Question. Like Sayse said in the comments: don’t use the same name for your variable as the name of the model. So change it to something like my_question = Question().
Change your linter to – flake8 and problem will go away.
回答 13
当我使用pylint_runner时发生此问题
所以我要做的是打开.pylintrc文件并将其添加
# List of members which are set dynamically and missed by pylint inference# system, and so shouldn't trigger E1101 when accessed. Python regular# expressions are accepted.
generated-members=objects
# List of members which are set dynamically and missed by pylint inference
# system, and so shouldn't trigger E1101 when accessed. Python regular
# expressions are accepted.
generated-members=objects