কীভাবে স্কেলএলচেমির ফলাফলটি JSON এ সিরিয়াল করবেন?


190

জ্যাঙ্গোর কাছে ডিবি থেকে জেএসওএন ফর্ম্যাটে ফিরে আসা ওআরএম মডেলের কিছু ভাল স্বয়ংক্রিয় সিরিয়ালাইজেশন রয়েছে।

কীভাবে JSON ফর্ম্যাটে SQLAlchemy ক্যোয়ারী ফলাফল সিরিয়ালাইজ করবেন?

আমি চেষ্টা করেছি jsonpickle.encodeতবে এটি ক্যোয়ারী অবজেক্টকেই এনকোড করে। আমি চেষ্টা করেছিলাম json.dumps(items)তবে তা ফিরে আসে

TypeError: <Product('3', 'some name', 'some desc')> is not JSON serializable

এসকিউএলএলকেমি ওআরএম অবজেক্টগুলিকে জেএসএন / এক্সএমএলকে সিরিয়াল করা কি এতই কঠিন? এর জন্য কোনও ডিফল্ট সিরিয়ালাইজার নেই? আজকাল ওআরএম ক্যোয়ারী ফলাফলগুলি ক্রমিক করা খুব সাধারণ কাজ।

আমার যা দরকার তা হল কেবল এসকিউএলএলচেমি কোয়েরির ফলাফলের জেএসএন বা এক্সএমএল ডেটা উপস্থাপনা।

জেএসএন / এক্সএমএল ফর্ম্যাটে এসকিউএএএলএলএইচির অবজেক্টের ক্যোয়ারী ফলাফল জাভাস্ক্রিপ্ট ডেটাগার্ডে ব্যবহার করা প্রয়োজন (জেকিউগ্রিড http://www.trirand.com/blog/ )


এটি আমার জন্য কাজ করে work এখানে লিংক বর্ণনা লিখুন
octaedro

উত্তর:


128

একটি সমতল বাস্তবায়ন

আপনি এই জাতীয় কিছু ব্যবহার করতে পারেন:

from sqlalchemy.ext.declarative import DeclarativeMeta

class AlchemyEncoder(json.JSONEncoder):

    def default(self, obj):
        if isinstance(obj.__class__, DeclarativeMeta):
            # an SQLAlchemy class
            fields = {}
            for field in [x for x in dir(obj) if not x.startswith('_') and x != 'metadata']:
                data = obj.__getattribute__(field)
                try:
                    json.dumps(data) # this will fail on non-encodable values, like other classes
                    fields[field] = data
                except TypeError:
                    fields[field] = None
            # a json-encodable dict
            return fields

        return json.JSONEncoder.default(self, obj)

এবং তারপরে JSON এ রূপান্তর করুন:

c = YourAlchemyClass()
print json.dumps(c, cls=AlchemyEncoder)

এটি এনকোডেবল নয় এমন ক্ষেত্রগুলিকে অগ্রাহ্য করবে (এগুলিকে 'কিছুই নয়' তে সেট করুন)।

এটি সম্পর্কগুলিকে অটো-প্রসারিত করে না (যেহেতু এটি স্ব-রেফারেন্সের দিকে নিয়ে যেতে পারে এবং চিরকালের জন্য লুপ)।

একটি পুনরাবৃত্ত, অ-বৃত্তাকার বাস্তবায়ন

তবে, যদি আপনি বরং চিরকালের জন্য লুপ করেন তবে আপনি এটি ব্যবহার করতে পারেন:

from sqlalchemy.ext.declarative import DeclarativeMeta

def new_alchemy_encoder():
    _visited_objs = []

    class AlchemyEncoder(json.JSONEncoder):
        def default(self, obj):
            if isinstance(obj.__class__, DeclarativeMeta):
                # don't re-visit self
                if obj in _visited_objs:
                    return None
                _visited_objs.append(obj)

                # an SQLAlchemy class
                fields = {}
                for field in [x for x in dir(obj) if not x.startswith('_') and x != 'metadata']:
                    fields[field] = obj.__getattribute__(field)
                # a json-encodable dict
                return fields

            return json.JSONEncoder.default(self, obj)

    return AlchemyEncoder

এবং তারপরে অবজেক্টগুলি এনকোড করুন:

print json.dumps(e, cls=new_alchemy_encoder(), check_circular=False)

এটি সমস্ত শিশু এবং তাদের সমস্ত শিশু এবং তাদের সমস্ত শিশুকে এনকোড করবে ... মূলত আপনার পুরো ডাটাবেসটিকে সম্ভাব্যভাবে এনকোড করবে। এটি এর আগে এনকোড হওয়া কোনও কিছুর কাছে পৌঁছালে এটি 'কিছুই নয়' হিসাবে এনকোড করবে।

একটি পুনরাবৃত্ত, সম্ভবত-বিজ্ঞপ্তি, নির্বাচনী বাস্তবায়ন

আরেকটি বিকল্প, সম্ভবত আরও ভাল, আপনি যে ক্ষেত্রগুলি প্রসারিত করতে চান তা নির্দিষ্ট করতে সক্ষম হবেন:

def new_alchemy_encoder(revisit_self = False, fields_to_expand = []):
    _visited_objs = []

    class AlchemyEncoder(json.JSONEncoder):
        def default(self, obj):
            if isinstance(obj.__class__, DeclarativeMeta):
                # don't re-visit self
                if revisit_self:
                    if obj in _visited_objs:
                        return None
                    _visited_objs.append(obj)

                # go through each field in this SQLalchemy class
                fields = {}
                for field in [x for x in dir(obj) if not x.startswith('_') and x != 'metadata']:
                    val = obj.__getattribute__(field)

                    # is this field another SQLalchemy object, or a list of SQLalchemy objects?
                    if isinstance(val.__class__, DeclarativeMeta) or (isinstance(val, list) and len(val) > 0 and isinstance(val[0].__class__, DeclarativeMeta)):
                        # unless we're expanding this field, stop here
                        if field not in fields_to_expand:
                            # not expanding this field: set it to None and continue
                            fields[field] = None
                            continue

                    fields[field] = val
                # a json-encodable dict
                return fields

            return json.JSONEncoder.default(self, obj)

    return AlchemyEncoder

আপনি এখন এটি দিয়ে কল করতে পারেন:

print json.dumps(e, cls=new_alchemy_encoder(False, ['parents']), check_circular=False)

উদাহরণস্বরূপ, কেবলমাত্র 'পিতামাতা' নামক এসকিউএএলএলচেমি ক্ষেত্রগুলি প্রসারিত করতে।


এটি একটি দুর্দান্ত প্রতিক্রিয়া, তবে আমি যখনই এটি "ফ্ল্যাটবিহীন পদ্ধতিগুলি, কোনও ধারণার সাথে সম্পর্ককে আঘাত করি তখনই" "বেসকোয়ারি" এনকোড করতে পারি না?
বেন কিলাহ

1
@ সাশাব যেখানে সম্পর্কের পুনরাবৃত্তি হয় সেই মামলার বিরুদ্ধে কীভাবে আরও দানবিক লক্ষ্যবস্তু করা যায়? উদাহরণস্বরূপ, যদি আমার online_orderএবং addressউভয়ই একটি সম্পর্কের সাথে থাকে userতবে এর সাথে একটি সম্পর্কও online_orderরয়েছে address। আমি যদি এই সমস্তটি সিরিয়াল করতে চাইতাম তবে আমাকে এর addressমধ্যে অন্তর্ভুক্ত fields_to_expandকরতে হবে তবে আমি এবং addressদুজনেরই সম্পর্কের কারণে আমি রিডান্টলি সিরিয়ালাইজ করতে চাই না । useronline_order
ক্রিসি

2
@ বেনকিলাহ আমাকে অনুমান করুন, আপনি ফ্লাস্ক-স্ক্যালএলচেমি ব্যবহার করছেন এবং আপনার মডেলগুলি বেস নয়, ডিবি মোডেল থেকে উত্তরাধিকার সূত্রে প্রাপ্ত। যদি এটি হয় তবে for field in [x for x in dir(obj) if not x.startswith('_') and x != 'metadata']:এমনটি পরিবর্তন করুন যাতে এটি পড়ে for field in [x for x in dir(obj) if not x.startswith('_') and x != 'metadata' and not x.startswith('query')]:। মনে রাখবেন এই সমাধানটি আপনাকে 'ক্যোয়ারী' নামের সাথে সম্পত্তি / সম্পর্ক রাখতে বাধা দেবে
পাকম্যান

আমার মতো একইভাবে, তবে আরও জটিল। stackoverflow.com/questions/7102754/…
tyan

2
আপনি আমার সমাধান github.com/n0nSmoker/SQLAlchemy-serializer
n0n স্মোকার

270

আপনি কেবল অভিধান হিসাবে আপনার অবজেক্টটি আউটপুট করতে পারেন:

class User:
   def as_dict(self):
       return {c.name: getattr(self, c.name) for c in self.__table__.columns}

এবং তারপরে আপনি User.as_dict()নিজের অবজেক্টটিকে সিরিয়ালাইজ করতে ব্যবহার করুন ।

রূপান্তরিত হিসাবে স্কেলচেমি সারি অবজেক্টে পাইথন ডিকের কাছে ব্যাখ্যা করা হয়েছে


2
@ চার্ল্যাক্স, আমি কীভাবে একটি তারিখটাইম ঠিক করব? এটি ব্যবহার করে আমি 'ডেটটাইম.ডেটটাইম' (2013, 3, 22, 16, 50, 11) জেএসএন সিরিয়ালাইজযোগ্য নয় 'যখন আমি জসন.ডাম্পগুলি করি
Asken

1
এটি JSONEncoderবিষয়টির দায়িত্ব । ডেটটাইম সহ কিছু বস্তুর জন্য নিজের এনকোডারকে সংজ্ঞায়িত করতে আপনি এটি সাবক্লাস করতে পারেন। মনে রাখবেন যে Flask, উদাহরণস্বরূপ, জেএসএন-এ বাক্সের বাইরে (সর্বশেষ সংস্করণ সহ) এনকোডিং ডেটটাইম সমর্থন করুন।
চার্লাক্স

3
আপনি যদি স্কেলচেমির "ঘোষিত" পদ্ধতি ব্যবহার করেন তবে আপনি কাস্টম বেস ক্লাসে এর মতো কিছু যুক্ত করতে পারেন - এটি আপনার পক্ষে খুব কার্যকর কারণ আপনি যে কোনও ওআরএম অবজেক্টে my_orm_object.to ডিক্ট () কল করতে পারেন। একইভাবে আপনি একটি টটসোন () পদ্ধতিটি সংজ্ঞায়িত করতে পারেন যা আপনার টুডিক্ট পদ্ধতি এবং তারিখগুলি,
ব্লবগুলি

7
ডেটটাইম সমর্থন করার জন্য:return {c.name: unicode(getattr(self, c.name)) for c in self.__table__.columns}
শোহম

1
আপনার শ্রেণীর ভেরিয়েবলগুলি আপনার কলামের নামগুলির মতো না হলে এটি কাজ করে না। পরিবর্তে ক্লাসের নামগুলি কীভাবে পাবেন?
জেমস বার্ক

55

আপনি একটি রো প্রক্সিকে এভাবে ডিকে রূপান্তর করতে পারেন:

 d = dict(row.items())

তারপরে এটি জেএসএনে সিরিয়াল করুন ( datetimeমানগুলির মতো জিনিসের জন্য আপনাকে একটি এনকোডার নির্দিষ্ট করতে হবে ) আপনি কেবল একটি রেকর্ড চান (এবং সম্পর্কিত রেকর্ডগুলির একটি সম্পূর্ণ শ্রেণিবদ্ধ নয়) এটি এতটা কঠিন নয়।

json.dumps([(dict(row.items())) for row in rs])

1
এটি আমার কাস্টম এসকিএল ক্যোয়ারির জন্য db.engine.con সংযুক্ত () সাথে কন: আরএসএস = কন.একসেকিউট (এসকিউএল)
জেজেড হিসাবে কাজ করে।

1
এটি অনেক বেশি সহজ এবং কাজ করে। এই উত্তর এবং গৃহীত উত্তরের মধ্যে পার্থক্য কী?
সুন্দীপ

46

আমি মার্শমালো ব্যবহার করার পরামর্শ দিচ্ছি । এটি আপনাকে সম্পর্ক এবং নেস্টেড অবজেক্টগুলিকে সমর্থন করে আপনার মডেল দৃষ্টান্ত উপস্থাপনের জন্য সিরিয়ালাইজার তৈরি করতে দেয়।

এখানে তাদের দস্তাবেজগুলির একটি সঙ্কুচিত উদাহরণ। ORM মডেলটি ধরুন Author:

class Author(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    first = db.Column(db.String(80))
    last = db.Column(db.String(80))

এই শ্রেণীর জন্য একটি মার্শমেলো স্কিমা এভাবে নির্মিত হয়:

class AuthorSchema(Schema):
    id = fields.Int(dump_only=True)
    first = fields.Str()
    last = fields.Str()
    formatted_name = fields.Method("format_name", dump_only=True)

    def format_name(self, author):
        return "{}, {}".format(author.last, author.first)

... এবং এটির মতো ব্যবহৃত:

author_schema = AuthorSchema()
author_schema.dump(Author.query.first())

... এর ফলে একটি আউটপুট উত্পাদন করা হবে:

{
        "first": "Tim",
        "formatted_name": "Peters, Tim",
        "id": 1,
        "last": "Peters"
}

তাদের সম্পূর্ণ ফ্লাস্ক-এসকিউএএলএলএকেমি উদাহরণ দেখুন

একটি লাইব্রেরি marshmallow-sqlalchemyবিশেষত এসকিউএএলএলকেমি এবং মার্শমেলো সংহত করে। সেই লাইব্রেরিতে, Authorউপরে বর্ণিত মডেলের স্কিমাটি দেখতে এরকম দেখাচ্ছে:

class AuthorSchema(ModelSchema):
    class Meta:
        model = Author

সংহতকরণ ক্ষেত্রের প্রকারগুলিকে এসকিউএএলএলচেমি Columnপ্রকার থেকে অনুমান করা যায় ।

মার্শম্যালো-স্ক্ল্যাচকেমি এখানে।


12
আমি মার্শম্যালো -স্ক্ল্যাচমি.ড্রেডহেডোকস.আইও / এএন / স্লেস্টও পেয়েছি যা স্কিমা প্রজন্মকে সহজতর করে
Foo L

41

পাইথন 3.7+ এবং ফ্লাস্ক 1.1+ বিল্ট-ইন ডেটাচ্লাস প্যাকেজটি ব্যবহার করতে পারে

from dataclasses import dataclass
from datetime import datetime
from flask import Flask, jsonify
from flask_sqlalchemy import SQLAlchemy


app = Flask(__name__)
db = SQLAlchemy(app)


@dataclass
class User(db.Model):
  id: int
  email: str

  id = db.Column(db.Integer, primary_key=True, auto_increment=True)
  email = db.Column(db.String(200), unique=True)


@app.route('/users/')
def users():
  users = User.query.all()
  return jsonify(users)  


if __name__ == "__main__":
  users = User(email="user1@gmail.com"), User(email="user2@gmail.com")
  db.create_all()
  db.session.add_all(users)
  db.session.commit()
  app.run()

/users/রুট এখন ব্যবহারকারীদের তালিকা ফিরে আসবে।

[
  {"email": "user1@gmail.com", "id": 1},
  {"email": "user2@gmail.com", "id": 2}
]

সম্পর্কিত মডেলগুলি স্বয়ংক্রিয়ভাবে সিরিয়াল করুন

@dataclass
class Account(db.Model):
  id: int
  users: User

  id = db.Column(db.Integer)
  users = db.relationship(User)  # User model would need a db.ForeignKey field

থেকে প্রতিক্রিয়া jsonify(account)এই হবে।

{  
   "id":1,
   "users":[  
      {  
         "email":"user1@gmail.com",
         "id":1
      },
      {  
         "email":"user2@gmail.com",
         "id":2
      }
   ]
}

ডিফল্ট JSON এনকোডারটি ওভাররাইট করুন

from flask.json import JSONEncoder


class CustomJSONEncoder(JSONEncoder):
  "Add support for serializing timedeltas"

  def default(o):
    if type(o) == datetime.timedelta:
      return str(o)
    elif type(o) == datetime.datetime:
      return o.isoformat()
    else:
      return super().default(o)

app.json_encoder = CustomJSONEncoder      

1
এটি দেখতে সঠিক ধরণের সরল looks এটি কি deserialization জন্য কাজ করে?
ইন্ডার2050

আপনি কীওয়ার্ড আর্গুমেন্ট আনপ্যাকিং ব্যবহার করে পার্সড জেএসওনের একটি অভিধানকে একটি মডেলে রূপান্তর করতে পারেন:data = request.json['user']; user = User(**data)
টম

3
নোট যে id: int = Columnকাজ করবে, তবে তা id = Columnকরবে না, মনে হচ্ছে আপনি জসনকে ক্ষেত্রটি সিরিয়ালায়িত করার জন্য স্থিতিশীল টাইপিং ঘোষণা করতে হবে, অন্যথায় আপনি একটি খালি {}অবজেক্ট পাবেন।
এমব্রয়াইজ রাবিয়ার

1
এটি আমার পক্ষে কাজ করেছিল, কেন এটি গৃহীত উত্তর নয়? ফ্লাস্ক-মার্শমেলোর সাথে এটির কাজ করতে আমি ঘন্টাখানেক ধরে অ্যাপ_কন্টেক্সের আশেপাশে খেলছি।
নিক ডেটা লে

1
আমার জন্যও কাজ করেছেন। মনে রাখবেন যদি আপনি পাইথন 3.6 আছি, আপনি শুধু এই প্যাকেজটি ইনস্টল করতে চাইবেন: pipenv install dataclasses। এবং তারপরে এটি ঠিক কাজ করবে।
আলেকসান্দ্রআহ্

14

ফ্লাস্ক-জসনটুলস প্যাকেজে আপনার মডেলগুলির জন্য জসনসিরাইজিবলবেজ বেস শ্রেণীর প্রয়োগ রয়েছে ।

ব্যবহার:

from sqlalchemy.ext.declarative import declarative_base
from flask.ext.jsontools import JsonSerializableBase

Base = declarative_base(cls=(JsonSerializableBase,))

class User(Base):
    #...

এখন Userমডেলটি যাদুকরীভাবে সিরিয়ালযোগ্য able

যদি আপনার কাঠামো ফ্লাস্ক না হয় তবে আপনি কেবল কোডটি দখল করতে পারেন


2
এটি কেবলমাত্র একক সারিতে ক্রমিকায়িত হওয়ায় এটি অর্ধেক সমস্যা সমাধান করে। কীভাবে পুরো ক্যোয়ারী ফলাফলকে সিরিয়ালাইজ করবেন?
স্টিভ বেনেট

@ স্টিভবেনেট জবাবটি এনকোড করতে jsontools এর jsonapi ব্যবহার করুন । এটি স্বয়ংক্রিয়ভাবে রিটার্ন অবজেক্টটি এনকোড করবে
টজোররিমুরিরি

আমি একটি খুব সহজ sqlalchemy মডেল আছে, এবং আমি পেয়ে করছি: TypeError: <0x03577A50 এ ORM.State বস্তুর> না তাদেরকে JSON serializable হয়
Matej

1
এটা তোলে স্পষ্টভাবে আমার মডেল বস্তুর উপর __json __ () কল করে অবশেষে কাজ: প্রত্যাবর্তন my_object .__ JSON __ ()
Matej

লাইব্রেরি ফ্লাস্ক ১.০ এবং এর চেয়ে উপরে এর সাথে কাজ করে না, যেহেতু import flask.ext.whateverএখন ফ্লাস্ক 1.0 তে সমর্থিত নয়।
আদর্শ মাদ্রেচা

14

সুরক্ষার কারণে আপনার কখনই মডেলের সমস্ত ক্ষেত্র ফেরা উচিত নয়। আমি তাদের বেছে বেছে বেছে নিতে পছন্দ করি।

ফ্লাস্কের জসন এনকোডিং এখন ইউআইডি, ডেটটাইম এবং সম্পর্কগুলিকে সমর্থন করে (এবং যুক্ত queryএবং query_classফ্লাস্ক_স্ক্ল্যাচেমি db.Modelক্লাসের জন্য)। আমি নীচে এনকোডারটি আপডেট করেছি:

অ্যাপ্লিকেশন / json_encoder.py

    from sqlalchemy.ext.declarative import DeclarativeMeta
    from flask import json


    class AlchemyEncoder(json.JSONEncoder):
        def default(self, o):
            if isinstance(o.__class__, DeclarativeMeta):
                data = {}
                fields = o.__json__() if hasattr(o, '__json__') else dir(o)
                for field in [f for f in fields if not f.startswith('_') and f not in ['metadata', 'query', 'query_class']]:
                    value = o.__getattribute__(field)
                    try:
                        json.dumps(value)
                        data[field] = value
                    except TypeError:
                        data[field] = None
                return data
            return json.JSONEncoder.default(self, o)

app/__init__.py

# json encoding
from app.json_encoder import AlchemyEncoder
app.json_encoder = AlchemyEncoder

এটির সাহায্যে আমি বৈকল্পিকভাবে একটি __json__সম্পত্তি যুক্ত করতে পারি যা আমি এনকোড করতে চাইছি এমন ক্ষেত্রগুলির তালিকা ফিরিয়ে দেয়:

app/models.py

class Queue(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    song_id = db.Column(db.Integer, db.ForeignKey('song.id'), unique=True, nullable=False)
    song = db.relationship('Song', lazy='joined')
    type = db.Column(db.String(20), server_default=u'audio/mpeg')
    src = db.Column(db.String(255), nullable=False)
    created_at = db.Column(db.DateTime, server_default=db.func.now())
    updated_at = db.Column(db.DateTime, server_default=db.func.now(), onupdate=db.func.now())

    def __init__(self, song):
        self.song = song
        self.src = song.full_path

    def __json__(self):
        return ['song', 'src', 'type', 'created_at']

আমি আমার দর্শনে @ জসনাপি যুক্ত করছি, ফলাফল তালিকাটি ফিরিয়ে দেব এবং তারপরে আমার ফলাফলটি নিম্নরূপ:

[

{

    "created_at": "Thu, 23 Jul 2015 11:36:53 GMT",
    "song": 

        {
            "full_path": "/static/music/Audioslave/Audioslave [2002]/1 Cochise.mp3",
            "id": 2,
            "path_name": "Audioslave/Audioslave [2002]/1 Cochise.mp3"
        },
    "src": "/static/music/Audioslave/Audioslave [2002]/1 Cochise.mp3",
    "type": "audio/mpeg"
}

]

সুন্দর! আবারও প্রমাণ করুন যে কখনও কখনও প্রতিটি বোকা সামান্য কাজের জন্য আপনার ফ্যাট প্যাকেজের প্রয়োজন হয় না - ডিএসএল শেখা "শক্ত" উপায়ে করা আরও কঠিন হতে পারে। আমি এখানে নামার আগে অনেকগুলি JSON এবং REST প্যাকেজ দেখেছি। এটা ঠিক যে, এই এখনও একটি প্যাকেজ প্রয়োজন, flask_jsontools (যোগ করার জন্য @jsonapiকরতে @app.routeমধ্যে views.py ইত্যাদি), কিন্তু আমি এটা সরলতা ভালোবাসি। আমি মনে করি এটি সস্তা ফ্লাস্ক তারিখের সময় যুক্ত করেছে তবে তারিখ নয় তাই আমি নিজেই এটি json_encoder.py এ যুক্ত করেছি : value=...^ if isinstance(value, date):^ data[field] = datetime.combine(value, time.min).isoformat()^ else:^try:...
জুন

10

আপনি এই হিসাবে SQLlchemy এর আত্মপরিচয় ব্যবহার করতে পারেন:

mysql = SQLAlchemy()
from sqlalchemy import inspect

class Contacts(mysql.Model):  
    __tablename__ = 'CONTACTS'
    id = mysql.Column(mysql.Integer, primary_key=True)
    first_name = mysql.Column(mysql.String(128), nullable=False)
    last_name = mysql.Column(mysql.String(128), nullable=False)
    phone = mysql.Column(mysql.String(128), nullable=False)
    email = mysql.Column(mysql.String(128), nullable=False)
    street = mysql.Column(mysql.String(128), nullable=False)
    zip_code = mysql.Column(mysql.String(128), nullable=False)
    city = mysql.Column(mysql.String(128), nullable=False)
    def toDict(self):
        return { c.key: getattr(self, c.key) for c in inspect(self).mapper.column_attrs }

@app.route('/contacts',methods=['GET'])
def getContacts():
    contacts = Contacts.query.all()
    contactsArr = []
    for contact in contacts:
        contactsArr.append(contact.toDict()) 
    return jsonify(contactsArr)

@app.route('/contacts/<int:id>',methods=['GET'])
def getContact(id):
    contact = Contacts.query.get(id)
    return jsonify(contact.toDict())

এখানে একটি উত্তর থেকে অনুপ্রাণিত হন: স্ক্লাচেমি সারি বস্তুকে পাইথন ডিকে রূপান্তর করুন


5

আরও বিস্তারিত ব্যাখ্যা। আপনার মডেলটিতে যোগ করুন:

def as_dict(self):
       return {c.name: str(getattr(self, c.name)) for c in self.__table__.columns}

str()তাই যদি পাইথন 2 ব্যবহার ব্যবহার পাইথন 3 জন্য unicode()। এটি তারিখগুলি ডিসেরায়ালাইজ করতে সহায়তা করবে। তাদের সাথে কাজ না করে আপনি এটিকে সরাতে পারেন।

আপনি এখন এই জাতীয় ডাটাবেস জিজ্ঞাসা করতে পারেন

some_result = User.query.filter_by(id=current_user.id).first().as_dict()

First()অদ্ভুত ত্রুটি এড়াতে প্রয়োজন। as_dict()এখন ফলাফল deserialize হবে। Deserialization পরে, এটি জসন থেকে প্রস্তুত প্রস্তুত

jsonify(some_result)

3

এটি এত সোজা নয়। এটি করার জন্য আমি কিছু কোড লিখেছি। আমি এখনও এটিতে কাজ করছি, এবং এটি MochiKit ফ্রেমওয়ার্ক ব্যবহার করে। এটি মূলত একটি প্রক্সি এবং নিবন্ধিত জেএসওএন রূপান্তরকারী ব্যবহার করে পাইথন এবং জাভাস্ক্রিপ্টের মধ্যে যৌগিক বিষয়গুলি অনুবাদ করে।

ডাটাবেস অবজেক্টের জন্য ব্রাউজারের দিকটি হল db.js এর জন্য প্রক্সি.জেএসসে বেসিক পাইথন প্রক্সি উত্স প্রয়োজন

পাইথনের পাশে বেস প্রক্সি মডিউল রয়েছে । তারপরে অবশেষে ওয়েবসারভার.পিতে স্কেলএলচেমি অবজেক্ট এনকোডার । এটি মডেল.পি ফাইলে পাওয়া মেটাডেটা এক্সট্র্যাক্টরের উপরও নির্ভর করে ।


একেবারে প্রথম নজরে জটিল ... আমার যা দরকার - তা হল জাভাস্ক্রিপ্ট ডাটাগার্ডে ব্যবহার করার জন্য জেএসএন / এক্সএমএল ফর্ম্যাটে এসকিউএএএলএলচেমি অবজেক্টের ক্যোয়ারী ফলাফল পাওয়া (জেকিউগ্রিড ট্রায়ার্যান্ড. com/ ব্লগ )
জেলিড

কখনও কখনও সমস্যাগুলি আপনার প্রথম নজরে যেমন উপস্থিত থাকে তার চেয়ে আরও জটিল হয় ... এটি বিদেশী কী হিসাবে প্রত্যাবর্তিত বস্তুগুলি পরিচালনা করে এবং গভীরভাবে নেস্টেড সম্পর্কের সাথে ঘটে যাওয়া অসীম পুনরাবৃত্তি এড়াতে চেষ্টা করে। তবে, আপনি সম্ভবত কিছু কাস্টম ক্যোয়ারী লিখতে পারেন যা কেবল বেস প্রকারগুলি দেয় এবং সরাসরি সিম্পজসনযুক্ত ব্যক্তিদের সিরিয়ালাইজ করে।
কিথ

1
ঠিক আছে, সম্ভবত আমি এসকিউএএলএলচেমি ব্যবহার করে ডিক্টের অনুসন্ধানের সাথে যাব এবং কেবল ওআরএম সংরক্ষণ / আপডেট ক্রিয়াকলাপ সম্পাদন করে ওআরএমের সুবিধা ব্যবহার করব।
জেলিড

3

মূল প্রশ্নটি কিছুক্ষণ পিছিয়ে যাওয়ার পরে, এখানে উত্তরগুলির সংখ্যা (এবং আমার নিজের অভিজ্ঞতা) বোঝায় যে এটি বিভিন্ন বাণিজ্য-অফের সাথে বিভিন্ন জটিলতার বিভিন্ন পদ্ধতির সাথে একটি অ-তুচ্ছ প্রশ্ন।

সে কারণেই আমি এসকিউএলথ্যানোর লাইব্রেরিটি তৈরি করেছি যা এসকিউএএলএলচেমির ঘোষিত ওআরএমকে কনফিগারযোগ্য সিরিয়ালাইজেশন / ডি-সিরিয়ালাইজেশন সমর্থন দিয়ে প্রসারিত করে যা আপনি একবার নজর রাখতে চাইতে পারেন।

গ্রন্থাগারটি সমর্থন করে:

  • পাইথন 2.7, 3.4, 3.5 এবং 3.6।
  • এসকিউএএচএলএলকেমি সংস্করণগুলি 0.9 এবং উচ্চতর
  • জেএসএন, সিএসভি, ওয়াইএএমএল, এবং পাইথন থেকে / থেকে সিরিয়ালাইজেশন / ডি-সিরিয়ালাইজেশন dict
  • ক্রমিকায়ন / কলাম / বৈশিষ্ট্য, সম্পর্ক, সংকর বৈশিষ্ট্য এবং সমিতি প্রক্সির ডি-সিরিয়ালাইজেশন
  • নির্দিষ্ট বিন্যাস এবং কলাম / সম্পর্ক / বৈশিষ্ট্যগুলির জন্য সিরিয়ালাইজেশন সক্ষম এবং অক্ষম করা (যেমন আপনি একটি অন্তর্মুখী password মান সমর্থন করতে চান , তবে কখনই আউটবাউন্ডকে অন্তর্ভুক্ত করবেন না )
  • প্রাক-সিরিয়ালাইজেশন এবং পোস্ট-ডিসিরিয়ালাইজেশন মান প্রক্রিয়াকরণ (বৈধতা বা ধরণের চাপের জন্য)
  • একটি চমত্কার সোজা সিনট্যাক্স যা উভয়ই পাইথোনিক এবং নির্বিশেষে এসকিউএলএলচেমির নিজস্ব পদ্ধতির সাথে সামঞ্জস্যপূর্ণ

আপনি এখানে (আমি আশা করি!) বিস্তৃত দস্তাবেজগুলি দেখতে পারেন: https://sqlathanor.readthedocs.io/en/latest

আশাকরি এটা সাহায্য করবে!


2

কাস্টম সিরিয়ালাইজেশন এবং deserialization।

"from_json" (শ্রেণি পদ্ধতি) জসন ডেটার উপর ভিত্তি করে একটি মডেল অবজেক্ট তৈরি করে।

"deserialize" কেবলমাত্র উদাহরণস্বরূপ বলা যেতে পারে এবং জেসন থেকে সমস্ত ডেটা মডেল উদাহরণে মার্জ করে।

"সিরিয়ালাইজ" - পুনরাবৃত্ত সিরিয়ালাইজেশন

__writ_only__ সম্পত্তি কেবল লেখার বৈশিষ্ট্য (উদাহরণস্বরূপ "পাসওয়ার্ড_হ্যাশ") সংজ্ঞায়িত করতে প্রয়োজন।

class Serializable(object):
    __exclude__ = ('id',)
    __include__ = ()
    __write_only__ = ()

    @classmethod
    def from_json(cls, json, selfObj=None):
        if selfObj is None:
            self = cls()
        else:
            self = selfObj
        exclude = (cls.__exclude__ or ()) + Serializable.__exclude__
        include = cls.__include__ or ()
        if json:
            for prop, value in json.iteritems():
                # ignore all non user data, e.g. only
                if (not (prop in exclude) | (prop in include)) and isinstance(
                        getattr(cls, prop, None), QueryableAttribute):
                    setattr(self, prop, value)
        return self

    def deserialize(self, json):
        if not json:
            return None
        return self.__class__.from_json(json, selfObj=self)

    @classmethod
    def serialize_list(cls, object_list=[]):
        output = []
        for li in object_list:
            if isinstance(li, Serializable):
                output.append(li.serialize())
            else:
                output.append(li)
        return output

    def serialize(self, **kwargs):

        # init write only props
        if len(getattr(self.__class__, '__write_only__', ())) == 0:
            self.__class__.__write_only__ = ()
        dictionary = {}
        expand = kwargs.get('expand', ()) or ()
        prop = 'props'
        if expand:
            # expand all the fields
            for key in expand:
                getattr(self, key)
        iterable = self.__dict__.items()
        is_custom_property_set = False
        # include only properties passed as parameter
        if (prop in kwargs) and (kwargs.get(prop, None) is not None):
            is_custom_property_set = True
            iterable = kwargs.get(prop, None)
        # loop trough all accessible properties
        for key in iterable:
            accessor = key
            if isinstance(key, tuple):
                accessor = key[0]
            if not (accessor in self.__class__.__write_only__) and not accessor.startswith('_'):
                # force select from db to be able get relationships
                if is_custom_property_set:
                    getattr(self, accessor, None)
                if isinstance(self.__dict__.get(accessor), list):
                    dictionary[accessor] = self.__class__.serialize_list(object_list=self.__dict__.get(accessor))
                # check if those properties are read only
                elif isinstance(self.__dict__.get(accessor), Serializable):
                    dictionary[accessor] = self.__dict__.get(accessor).serialize()
                else:
                    dictionary[accessor] = self.__dict__.get(accessor)
        return dictionary

2

এখানে একটি সমাধান রয়েছে যা আপনাকে আপনার আউটপুটে যতটা গভীর যেতে চাইবে সেই সম্পর্কগুলি নির্বাচন করতে দেয়। দ্রষ্টব্য: এটি একটি সম্পূর্ণ লেখার পরিবর্তে একটি ডিক্ট / স্ট্রিংকে তালিকার চেয়ে আরগ হিসাবে গ্রহণ করে। কিছু জিনিস ঠিক করে ..

def deep_dict(self, relations={}):
    """Output a dict of an SA object recursing as deep as you want.

    Takes one argument, relations which is a dictionary of relations we'd
    like to pull out. The relations dict items can be a single relation
    name or deeper relation names connected by sub dicts

    Example:
        Say we have a Person object with a family relationship
            person.deep_dict(relations={'family':None})
        Say the family object has homes as a relation then we can do
            person.deep_dict(relations={'family':{'homes':None}})
            OR
            person.deep_dict(relations={'family':'homes'})
        Say homes has a relation like rooms you can do
            person.deep_dict(relations={'family':{'homes':'rooms'}})
            and so on...
    """
    mydict =  dict((c, str(a)) for c, a in
                    self.__dict__.items() if c != '_sa_instance_state')
    if not relations:
        # just return ourselves
        return mydict

    # otherwise we need to go deeper
    if not isinstance(relations, dict) and not isinstance(relations, str):
        raise Exception("relations should be a dict, it is of type {}".format(type(relations)))

    # got here so check and handle if we were passed a dict
    if isinstance(relations, dict):
        # we were passed deeper info
        for left, right in relations.items():
            myrel = getattr(self, left)
            if isinstance(myrel, list):
                mydict[left] = [rel.deep_dict(relations=right) for rel in myrel]
            else:
                mydict[left] = myrel.deep_dict(relations=right)
    # if we get here check and handle if we were passed a string
    elif isinstance(relations, str):
        # passed a single item
        myrel = getattr(self, relations)
        left = relations
        if isinstance(myrel, list):
            mydict[left] = [rel.deep_dict(relations=None)
                                 for rel in myrel]
        else:
            mydict[left] = myrel.deep_dict(relations=None)

    return mydict

সুতরাং উদাহরণস্বরূপ ব্যক্তি / পরিবার / বাড়ি / ঘরগুলি ব্যবহার করে ... এটিকে জসনে রূপান্তর করা আপনার যা দরকার তা হল

json.dumps(person.deep_dict(relations={'family':{'homes':'rooms'}}))

এটি ঠিক আছে আমি কেবল আপনার বেস ক্লাসে রাখি বলে মনে করি যাতে সমস্ত বস্তুর এটি থাকে। আমি আপনাদের কাছে জসন এনকোডিং রেখে যাব ...
tahoe

মনে রাখবেন যে এই সংস্করণটি সমস্ত তালিকার সম্পর্ক পাবে তাই এক টন আইটেমের সাথে সম্পর্ক সরবরাহ করার ক্ষেত্রে সতর্ক থাকুন ...
tahoe

1
def alc2json(row):
    return dict([(col, str(getattr(row,col))) for col in row.__table__.columns.keys()])

আমি ভেবেছিলাম আমি এই সাথে একটি সামান্য কোড গল্ফ খেলব।

এফওয়াইআই: আমি ব্যবসার প্রয়োজনীয়তা অনুসারে আলাদাভাবে ডিজাইন করা স্কিমা তৈরি করার পরে আমি অটোম্যাপ_বেসটি ব্যবহার করছি । আমি আজই এসকিএএলএলএকমি ব্যবহার শুরু করেছি তবে ডকুমেন্টেশনে বলা হয়েছে যে অটোম্যাপ_বেসটি ডিকোরেচারি_বেসে একটি এক্সটেনশন যা মনে হয় এসকিউএলএলমি র ওআরএম-এর আদর্শ দৃষ্টান্ত বলে মনে হয় তাই আমি বিশ্বাস করি এটি কাজ করা উচিত।

এটি তেজরিরিমোরির সমাধান অনুসারে বিদেশী কীগুলি অনুসরণ করে অভিনবতা পায় না , তবে এটি কলামগুলির সাথে মানগুলির সাথে মেলে এবং পাইথন প্রকারকে স্ট্রিং () দ্বারা ক্যান্ডেল করে - কলামের মানগুলি ইঙ্গিত করে। আমাদের মানগুলিতে পাইথনের ডেটটাইম.টাইম এবং দশমিক D দশমিক শ্রেণির ধরণের ফলাফল থাকে যাতে এটি কাজটি করে।

আশা করি এটি কোনও পথিককে সহায়তা করবে!


1

আমি জানি এটি বেশ পুরানো পোস্ট। আমি @ সাশাব দ্বারা প্রদত্ত সমাধান নিয়েছি এবং আমার প্রয়োজন অনুসারে সংশোধন করেছি।

আমি এতে নিম্নলিখিত বিষয়গুলি যুক্ত করেছি:

  1. ক্ষেত্র উপেক্ষা তালিকা: ক্রমিকায়নের সময় ক্ষেত্রের তালিকা উপেক্ষা করা হবে
  2. ক্ষেত্র প্রতিস্থাপনের তালিকা: সিরিয়ালাইজ করার সময় মানগুলির দ্বারা প্রতিস্থাপন করতে ক্ষেত্রের নাম সম্বলিত একটি অভিধান।
  3. সরানো পদ্ধতি এবং বেসকিউয়ারি সিরিয়ালাইজড হচ্ছে

আমার কোডটি নিম্নরূপ:

def alchemy_json_encoder(revisit_self = False, fields_to_expand = [], fields_to_ignore = [], fields_to_replace = {}):
   """
   Serialize SQLAlchemy result into JSon
   :param revisit_self: True / False
   :param fields_to_expand: Fields which are to be expanded for including their children and all
   :param fields_to_ignore: Fields to be ignored while encoding
   :param fields_to_replace: Field keys to be replaced by values assigned in dictionary
   :return: Json serialized SQLAlchemy object
   """
   _visited_objs = []
   class AlchemyEncoder(json.JSONEncoder):
      def default(self, obj):
        if isinstance(obj.__class__, DeclarativeMeta):
            # don't re-visit self
            if revisit_self:
                if obj in _visited_objs:
                    return None
                _visited_objs.append(obj)

            # go through each field in this SQLalchemy class
            fields = {}
            for field in [x for x in dir(obj) if not x.startswith('_') and x != 'metadata' and x not in fields_to_ignore]:
                val = obj.__getattribute__(field)
                # is this field method defination, or an SQLalchemy object
                if not hasattr(val, "__call__") and not isinstance(val, BaseQuery):
                    field_name = fields_to_replace[field] if field in fields_to_replace else field
                    # is this field another SQLalchemy object, or a list of SQLalchemy objects?
                    if isinstance(val.__class__, DeclarativeMeta) or \
                            (isinstance(val, list) and len(val) > 0 and isinstance(val[0].__class__, DeclarativeMeta)):
                        # unless we're expanding this field, stop here
                        if field not in fields_to_expand:
                            # not expanding this field: set it to None and continue
                            fields[field_name] = None
                            continue

                    fields[field_name] = val
            # a json-encodable dict
            return fields

        return json.JSONEncoder.default(self, obj)
   return AlchemyEncoder

আশা করি এটি কাউকে সাহায্য করবে!


1

এসকিউএএলএলচেমিতে অন্তর্নির্মিত সিরিয়ালাইজারটি ব্যবহার করুন :

from sqlalchemy.ext.serializer import loads, dumps
obj = MyAlchemyObject()
# serialize object
serialized_obj = dumps(obj)

# deserialize object
obj = loads(serialized_obj)

আপনি যদি সেশনের মধ্যে অবজেক্টটি স্থানান্তর করেন তবে বর্তমান সেশনটি ব্যবহার করে অবজেক্টটি আলাদা করা মনে রাখবেন session.expunge(obj)। এটি আবার সংযুক্ত করার জন্য, ঠিক করুন session.add(obj)


নিফ্টি, তবে জেএসএনে রূপান্তর করে না।
ব্লেকভ

2
জেএসওএন 'সিরিয়ালাইজেশন' এর জন্য মার্শম্যালো-স্ক্ল্যাচ-চেক আউট করুন । আপনি যখন ক্লায়েন্টের কাছে অবজেক্ট প্রকাশ করছেন তখন অবশ্যই সেরা সমাধান। মার্শম্যালো
-স্ক্ল্যাচেমি.ড্রেডহেডোকস.আইও

সিরিয়ালাইজার মডিউলটি কেবল ক্যোয়ারী কাঠামোর জন্য উপযুক্ত। এটির জন্য দরকার নেই: ব্যবহারকারী-সংজ্ঞায়িত শ্রেণীর উদাহরণ। এগুলিতে সাধারণত ক্ষেত্রে ইঞ্জিন, সেশন বা এক্সপ্রেশন কন্সট্রাক্টসের কোনও উল্লেখ থাকে না এবং সরাসরি সিরিয়ালাইজড করা যায়।
থোমাসড

1

নিম্নলিখিত কোডটি স্ক্রালেচেমির ফলাফলকে জসনকে সিরিয়ালাইজ করবে।

import json
from collections import OrderedDict


def asdict(self):
    result = OrderedDict()
    for key in self.__mapper__.c.keys():
        if getattr(self, key) is not None:
            result[key] = str(getattr(self, key))
        else:
            result[key] = getattr(self, key)
    return result


def to_array(all_vendors):
    v = [ ven.asdict() for ven in all_vendors ]
    return json.dumps(v) 

কলিং মজা,

def all_products():
    all_products = Products.query.all()
    return to_array(all_products)

1

AlchemyEncoder দুর্দান্ত কিন্তু কখনও কখনও দশমিক মান সঙ্গে ব্যর্থ হয়। এখানে একটি উন্নত এনকোডার রয়েছে যা দশমিক সমস্যার সমাধান করে -

class AlchemyEncoder(json.JSONEncoder):
# To serialize SQLalchemy objects 
def default(self, obj):
    if isinstance(obj.__class__, DeclarativeMeta):
        model_fields = {}
        for field in [x for x in dir(obj) if not x.startswith('_') and x != 'metadata']:
            data = obj.__getattribute__(field)
            print data
            try:
                json.dumps(data)  # this will fail on non-encodable values, like other classes
                model_fields[field] = data
            except TypeError:
                model_fields[field] = None
        return model_fields
    if isinstance(obj, Decimal):
        return float(obj)
    return json.JSONEncoder.default(self, obj)

1

স্ক্লালচেমি ব্যবহার করার সময় কোনও ডিবিতে সংযোগ স্থাপন করতে আমি এটি একটি সহজ সমাধান যা অত্যন্ত কনফিগারযোগ্য। পান্ডা ব্যবহার করুন।

import pandas as pd
import sqlalchemy

#sqlalchemy engine configuration
engine = sqlalchemy.create_engine....

def my_function():
  #read in from sql directly into a pandas dataframe
  #check the pandas documentation for additional config options
  sql_DF = pd.read_sql_table("table_name", con=engine)

  # "orient" is optional here but allows you to specify the json formatting you require
  sql_json = sql_DF.to_json(orient="index")

  return sql_json

0

ফ্লাস্কের অধীনে, এটি কাজ করে এবং ডেটাটাইম ক্ষেত্রগুলি পরিচালনা করে, প্রকারের ক্ষেত্রকে রূপান্তর
'time': datetime.datetime(2018, 3, 22, 15, 40)করে
"time": "2018-03-22 15:40:00":

obj = {c.name: str(getattr(self, c.name)) for c in self.__table__.columns}

# This to get the JSON body
return json.dumps(obj)

# Or this to get a response object
return jsonify(obj)

0

Utf-8 দিয়ে নির্মিত সিরিয়ালাইজার চোকগুলি কিছু ইনপুটগুলির জন্য অবৈধ শুরু বাইট ডিকোড করতে পারে না। পরিবর্তে, আমি সঙ্গে গিয়েছিলাম:

def row_to_dict(row):
    temp = row.__dict__
    temp.pop('_sa_instance_state', None)
    return temp


def rows_to_list(rows):
    ret_rows = []
    for row in rows:
        ret_rows.append(row_to_dict(row))
    return ret_rows


@website_blueprint.route('/api/v1/some/endpoint', methods=['GET'])
def some_api():
    '''
    /some_endpoint
    '''
    rows = rows_to_list(SomeModel.query.all())
    response = app.response_class(
        response=jsonplus.dumps(rows),
        status=200,
        mimetype='application/json'
    )
    return response

0

হতে পারে আপনি এর মতো ক্লাস ব্যবহার করতে পারেন

from sqlalchemy.ext.declarative import declared_attr
from sqlalchemy import Table


class Custom:
    """Some custom logic here!"""

    __table__: Table  # def for mypy

    @declared_attr
    def __tablename__(cls):  # pylint: disable=no-self-argument
        return cls.__name__  # pylint: disable= no-member

    def to_dict(self) -> Dict[str, Any]:
        """Serializes only column data."""
        return {c.name: getattr(self, c.name) for c in self.__table__.columns}

Base = declarative_base(cls=Custom)

class MyOwnTable(Base):
    #COLUMNS!

সেই সাথে সমস্ত বস্তুর to_dictপদ্ধতি আছে


0

কিছু কাঁচা এসকিএল এবং অপরিজ্ঞাত বস্তু ব্যবহার cursor.descriptionকরার সময় , আমি যা খুঁজছিলাম তা পেয়ে উপস্থিত হয়েছিল:

with connection.cursor() as cur:
    print(query)
    cur.execute(query)
    for item in cur.fetchall():
        row = {column.name: item[i] for i, column in enumerate(cur.description)}
        print(row)

0
step1:
class CNAME:
   ...
   def as_dict(self):
       return {item.name: getattr(self, item.name) for item in self.__table__.columns}

step2:
list = []
for data in session.query(CNAME).all():
    list.append(data.as_dict())

step3:
return jsonify(list)

3
কোনও ব্যাখ্যা ছাড়াই কোড ডাম্প খুব কমই সহায়ক। স্ট্যাক ওভারফ্লো শিখার বিষয়ে, অন্ধভাবে অনুলিপি করে অনুলিপি করার জন্য স্নিপেট সরবরাহ করে না। দয়া করে আপনার প্রশ্নটি সম্পাদনা করুন এবং ওপি কী সরবরাহ করেছে তার থেকে এটি কীভাবে ভাল কাজ করে তা ব্যাখ্যা করুন।
ক্রিস

-2

আমার গ্রহণ (খুব বেশি?) অভিধান ব্যবহার করছে:

def serialize(_query):
    #d = dictionary written to per row
    #D = dictionary d is written to each time, then reset
    #Master = dictionary of dictionaries; the id Key (int, unique from database) 
    from D is used as the Key for the dictionary D entry in Master
    Master = {}
    D = {}
    x = 0
    for u in _query:
        d = u.__dict__
        D = {}
        for n in d.keys():
           if n != '_sa_instance_state':
                    D[n] = d[n]
        x = d['id']
        Master[x] = D
    return Master

JSON হিসাবে আউটপুটগুলি মুদ্রণের জন্য ফ্লাস্ক (jsonify সহ) এবং ফ্লাস্ক_স্ক্ল্যাচেমিকে নিয়ে চলছে।

জসনাইফাই (সিরিয়ালাইজ ()) দিয়ে ফাংশনটি কল করুন।

আমি এতক্ষণ চেষ্টা করেছি এমন সমস্ত এসকিউএএলএলকেমি প্রশ্নের সাথে কাজ করে (এসকিউএলাইট 3 চলছে)

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.