I know I am not the first person to ask this question, but I still couldn't find an answer for my situation.
I have a Django environment that works very well, I know I only have one (1) settings.py file and I know that my environment accesses it correctly.
I recently added a new endpoint to my project. I defined its URL in urls.py
urlpatterns = [
...
url(PREFIX + r"^v1/alerts/debug$", alerts_views_v1.debug_trigger_alert_notification),
...
]
It is connected to a method that is in a the file alerts/views_v1.py but is not in any particular class:
#api_view(["POST"])
def debug_trigger_alert_notification(request):
"""
Trigger an Alert. i.e. Create an Alertnotification.
This function is meant to be called by the scheduler service.
"""
workspace_slug = request.data.pop("workspace")
with in_database(workspace_slug, write=True):
serializer = AlertNotificationSerializer(data=request.data)
if serializer.is_valid(raise_exception=True):
serializer.save()
return Response()
When I send a request to this URL, I receive the following 500 error:
ImproperlyConfigured at /v1/alerts/debug
settings.DATABASES is improperly configured. Please supply the ENGINE value. Check settings documentation for more details.
In my settings.py file, my DATABASES variable seems correct (though it is built in a roundabout way):
DEFAULT_DATABASES = {
"default": { # This DB is supposed to always have the latest version of the schema described by the Django Model
"ENGINE": "django.db.backends.postgresql",
"NAME": os.environ["REFERENCE_DB_NAME"],
"USER": os.environ["DB_USER"],
"PASSWORD": os.environ["DB_PASSWORD"],
"HOST": os.environ["DB_HOST"],
"PORT": os.environ["DB_PORT"],
}
}
# Retrieve all existing workspace databases:
try:
_existing_workspace_database_names = ExistingWorkspace(
db_user=DEFAULT_DATABASES["default"]["USER"],
db_host=DEFAULT_DATABASES["default"]["HOST"],
db_password=DEFAULT_DATABASES["default"]["PASSWORD"],
).list_existing_workspaces()
except Exception as e:
log.critical("settings.py: Error retrieving list of existing databases.")
raise e
else:
log.info("settings.py: Successfully retrieved list of existing databases.")
WORKSPACE_DATABASES = {
db_name_to_slug(existing_workspace_database_name): {
"ENGINE": "django.db.backends.postgresql",
"NAME": existing_workspace_database_name,
"USER": os.environ["DB_USER"],
"PASSWORD": os.environ["DB_PASSWORD"],
"HOST": os.environ["DB_HOST"],
"PORT": os.environ["DB_PORT"],
}
for existing_workspace_database_name in _existing_workspace_database_names
}
DATABASES = {**DEFAULT_DATABASES, **WORKSPACE_DATABASES}
DATABASE_ROUTERS = ["dynamic_db_router.DynamicDbRouter"]
What can I do?
Related
i have a django-restframwork project where i have set MEDIA_URL in settings.py file. the problen is when serialize a model i get the file name with media prefixed.
Here the response i am getting
{
"employees": [
{
"id": 1,
"name": "neki",
"doc": "/media/simple-nature-wallpapers-free-download-for-desktop-45.jpg"
}
]
}
But i want the response without media prefixed like this
{
"employees": [
{
"id": 1,
"name": "neki",
"doc": "simple-nature-wallpapers-free-download-for-desktop-45.jpg"
}
]
}
I have two solutions. Both of them have some problems
I can remove MEDIA_URL from setting.py file (Problem is i cant access the file from storage)
Or i can save the file name as models.CharField(). (Problem is i cant save file from ModelSerializer automatically)
So my Question is how to solve these problem.
Override the to_represenataion() method of serializer
class YourSerializer(.....):
# your code
def to_representation(self, instance):
rep = super(YourSerializer,self).to_representation(instance)
try:
rep['doc'] = rep['doc'].split('/')[-1]
except KeyError:
return rep
return rep
If you sahre your serializer and views, i can help you better. but the short answer is:
if you send this response with post method , you can override create method in your views(if you are using generics.CreateAPIView). if get, override retrive and ... .
and then change your response as you want. you access to your response data there.
share your view and serializer for more cleare answer.
When I request my user data from localhost:8000/users, I get users that look like this:
{
"username": "iv4ha05k",
"email": "xxxx#xxx.com",
"profile": {
"image": "http://localhost:8000/media/images-4.jpg"
},
"pk": 303
},
But, if I request user data from the django manage shell, the data will look like this:
{
"username": "iv4ha05k",
"email": "xxxx#xxx.com",
"profile": {
"image": "/media/images-4.jpg"
},
"pk": 303
},
Notice how the image url becomes truncated. I am querying the same exact database in the same exact state, and it has nothing to do with migrations or anything of the like. I discovered this issue when trying to write custom API views. When I would query the User viewset, it would return data with the full image address. But, when I try to write a custom API view that queries the user database, it will return it with the truncated address. I am using django's FileSystemStorage, if that helps anyone.. Thanks.
I'm writing a new backend API using Django.
I have configured the following values in settings.py:
CACHES = {
'default': {
'BACKEND': 'django.contrib.sessions.backends.cached_db'
}
}
SESSION_ENGINE = 'django.contrib.sessions.backends.signed_cookies'
I can't figure out how to write the session properties to the database. Anyone have any idea?
You have to activate also django.contrib.sessions.middleware.SessionMiddleware middleware first to have access to request.session dictionary in your views.
Here's simplistic example how to use request.session, taken directly from Django session documentation:
def post_comment(request, new_comment):
if request.session.get('has_commented', False):
return HttpResponse("You've already commented.")
c = comments.Comment(comment=new_comment)
c.save()
request.session['has_commented'] = True
return HttpResponse('Thanks for your comment!')
i want to customize the error response from django rest framework.
this is slandered error response from django rest..
{
"style": [
"This field is required."
],
"code": [
"code must be in 60 to 120 chars."
]
}
i want to customize it like....
{
"style": [
"error_code":"20"
"error_message":"This field is required."
],
"code": [
"error_code":"22"
"error_message":"code must be in 60 to 120 chars."
]
}
I had the same problem in showing errors. First of all you should know that you can't use key-value pairs in a list (i.e. "style": ["error_code": "20", "error_message": "This field is required."]) and you should change your type to dictionary if you want to convert your error to this custom type. One easy way is that you can have your own custom exception handler and then tell rest framework to use that exception handler to customize your exceptions. First you should add the following line in your project settings.py:
REST_FRAMEWORK = {
'EXCEPTION_HANDLER': 'utils.exception_handlers.custom_exception_handler', # You should add the path to your custom exception handler here.
}
Which tells that all of the exceptions should pass through this handler. After that you should add python file and add your codes in it (use this file path in your settings.py which mentioned before). In following code you can see an example of this handler:
from rest_framework.exceptions import ErrorDetail
from rest_framework.views import exception_handler
def custom_exception_handler(exc, context):
# Call REST framework's default exception handler first,
# to get the standard error response.
# Call REST framework's default exception handler first,
# to get the standard error response.
response = exception_handler(exc, context)
custom_data = {}
if isinstance(response.data, dict):
for key, value in response.data.items():
if value and isinstance(value, list) and isinstance(value[0], ErrorDetail):
custom_response[key] = {
"error_message": str(value[0]),
"error_code": response.status_code # or any custom code that you need
}
else:
break
if custom_data:
response.data = custom_data
return response
Note: This was a quick example and you should test your APIs to make sure that everything works.
I saw swagger documentation of Flask and Django. In Flask I can design and document my API hand-written.(Include which fields are required, optional etc. under parameters sections).
Here's how we do in Flask
class Todo(Resource):
"Describing elephants"
#swagger.operation(
notes='some really good notes',
responseClass=ModelClass.__name__,
nickname='upload',
parameters=[
{
"name": "body",
"description": "blueprint object that needs to be added. YAML.",
"required": True,
"allowMultiple": False,
"dataType": ModelClass2.__name__,
"paramType": "body"
}
],
responseMessages=[
{
"code": 201,
"message": "Created. The URL of the created blueprint should be in the Location header"
},
{
"code": 405,
"message": "Invalid input"
}
]
)
I can chose which parameters to include, and which not. But how do I implement the same in Django? Django-Swagger Document in
not good at all. My main issue is how do I write my raw-json in Django.
In Django it automates it which does not allows me to customize my json. How do I implement the same kind of thing on Django?
Here is models.py file
class Controller(models.Model):
id = models.IntegerField(primary_key = True)
name = models.CharField(max_length = 255, unique = True)
ip = models.CharField(max_length = 255, unique = True)
installation_id = models.ForeignKey('Installation')
serializers.py
class ActionSerializer(serializers.ModelSerializer):
class Meta:
model = Controller
fields = ('installation',)
urls.py
from django.conf.urls import patterns, url
from rest_framework.urlpatterns import format_suffix_patterns
from modules.actions import views as views
urlpatterns = patterns('',
url(r'(?P<installation>[0-9]+)', views.ApiActions.as_view()),
)
views.py
class ApiActions(APIView):
"""
Returns controllers List
"""
model = Controller
serializer_class = ActionSerializer
def get(self, request, installation,format=None):
controllers = Controller.objects.get(installation_id = installation)
serializer = ActionSerializer(controllers)
return Response(serializer.data)
My questions are
1) If I need to add a field say xyz, which is not in my models how do I add it?
2) Quiet similar to 1st, If i need to add a field which accepts values b/w 3 provided values,ie a dropdown. how do I add it?
3) How I add an optional field? (since in case of PUT request, I might only update 1 field and rest leave it blank, which means optional field).
4) Also how do I add a field that accepts the json string, as this api does?
Thanks
I can do all of these things in Flask by hardcoding my api. But in Django, it automates from my models, which does not(as I believe) gives me the access to customize my api. In Flask, I just need to write my API with hands and then integrate with the Swagger. Does this same thing exist in Django?
Like I just need to add the following json in my Flask code and it will answer all my questions.
# Swagger json:
"models": {
"TodoItemWithArgs": {
"description": "A description...",
"id": "TodoItem",
"properties": {
"arg1": { # I can add any number of arguments I want as per my requirements.
"type": "string"
},
"arg2": {
"type": "string"
},
"arg3": {
"default": "123",
"type": "string"
}
},
"required": [
"arg1",
"arg2" # arg3 is not mentioned and hence 'opional'
]
},
Would this work:
class TriggerView(APIView):
"""
This text is the description for this API
mykey -- My Key parameter
"""
authentication_classes = (BasicAuthentication,)
permission_classes = (IsAuthenticated,)
def post(self, request, format=None):
print request.DATA
return Response(status=status.HTTP_202_ACCEPTED)
the POST request:
Authorization:Basic YWRtaW46cGFzcw==
Content-Type:application/json
{"mykey": "myvalue"}